I am trying to make a simple top down shooter. When the user presses W, A, S or D a 'bullet' (rectangle) will come out of the 'shooter'. With my code, you can only shoot one bullet per direction until it reaches the end of the screen. Is there a way to make it so they (the user) can shoot multiple bullets in one direction?
Here's my code:
package topdownshooter;
import processing.core.PApplet;
import processing.core.PImage;
public class TopDownShooter extends PApplet {
PImage shooter;
float shooterX = 400;
float shooterY = 300;
float u_bulletSpeed;
float l_bulletSpeed;
float d_bulletSpeed;
float r_bulletSpeed;
boolean shootUp = false;
boolean shootLeft = false;
boolean shootDown = false;
boolean shootRight = false;
public static void main(String[] args) {
PApplet.main("topdownshooter.TopDownShooter");
}
public void setup() {
shooter = loadImage("shooter.png");
}
public void settings() {
size(800, 600);
}
public void keyPressed() {
if(key == 'w') {
shootUp = true;
}
if(key == 'a') {
shootLeft = true;
}
if(key == 's') {
shootDown = true;
}
if(key == 'd') {
shootRight = true;
}
}
public void draw() {
background(206);
imageMode(CENTER);
image(shooter, shooterX, shooterY);
if(shootUp == true) {
rect(shooterX, shooterY-u_bulletSpeed, 5, 5);
u_bulletSpeed += 2;
if(u_bulletSpeed > 300) {
u_bulletSpeed = 0;
shootUp = false;
}
}
if(shootLeft == true) {
rect(shooterX-l_bulletSpeed, shooterY, 5, 5);
l_bulletSpeed += 2;
if(l_bulletSpeed > 400) {
l_bulletSpeed = 0;
shootLeft = false;
}
}
if(shootDown == true) {
rect(shooterX, shooterY+d_bulletSpeed, 5, 5);
d_bulletSpeed += 2;
if(d_bulletSpeed > 300) {
d_bulletSpeed = 0;
shootDown = false;
}
}
if(shootRight == true) {
rect(shooterX+r_bulletSpeed, shooterY, 5, 5);
r_bulletSpeed += 2;
if(r_bulletSpeed > 400) {
r_bulletSpeed = 0;
shootRight = false;
}
}
}
}
The language is processing and I am using the eclipse IDE.
Thanks!
Here's what I would do if I were you. First I'd encapsulate your bullet data into a class, like this:
class Bullet{
float x;
float y;
float xSpeed;
float ySpeed;
// you probably want a constructor here
void drawBullet(){
// bullet drawing code
}
}
Then I'd create an ArrayList that holds Bullet instances:
ArrayList<Bullet> bullets = new ArrayList<Bullet>();
To add a bullet, I'd create a new instance and add it to the ArrayList like this:
bullets.add(new Bullet(bulletX, bulletY));
Then to draw the bullets, I'd iterate over the ArrayList and call the corresponding function:
for(Bullet b : bullets){
b.drawBullet();
}
Shameless self-promotion:
Here is a tutorial on creating classes.
Here is a tutorial on using ArrayLists.
Related
I'm very new to coding and was wondering how I could make this image move to the right. I added all of my code so that it would be a bit more understandable for what's going on. The moveRight command will not actually move the png to the right which is why I need help fixing and understanding why it won't work. If someone can please help me it would be greatly appreciated.
PImage background, backgroundGameState1, headbasketballbackground, player1, player2;
boolean moveRight, moveLeft;
int canvasSizeX= 1000;
int canvasSizeY = 600;
int mainBackgroundX = 1000;
int mainBackgroundY = 600;
int gameState1 = 1;
int player1X = 100;
int player1Y = 200;
int player2X = 100;
int player2Y = 200;
int backgroundGameState1X= 1000;
int backgroundGameState1Y=600;
int time;
int player1MovmentX = 100;
int player2MovmentX = 700;
void setup() {
//size of canvas
size(1000, 600);
//Loaded images and called them, also made sure to resize them in order to match the canvas size or to make program more asthetically pleasing
background = loadImage("headbasketballbackground.png");
background.resize(mainBackgroundX, mainBackgroundY);
backgroundGameState1 = loadImage("backgroundgamestate1.png");
backgroundGameState1.resize(backgroundGameState1X, backgroundGameState1Y);
player1 = loadImage("steph.png");
player1.resize(player1X, player1Y);
player2 = loadImage("paul.png");
player2.resize(player2X, player2Y);
time=millis();
}
void draw() {
if (gameState1 == 1) {
background(backgroundGameState1);
if (millis() > time + 1000) {
text("Click On Space To Enter The Game!", 100, 100);
textSize(50);
// delay(3000);
}
drawGameState1();
}
if (gameState1 == 2) {
background(background);
image(player1, player1MovmentX, 300);
image(player2, player2MovmentX, 300);
}
// if (gameState2 == 3) {
// text("Congrats you won!");
//}
}
void drawGameState1() {
}
void drawGameState2() {
drawPlayer1Movment();
}
void drawPlayer1Movment(){
if(moveRight){
player1MovmentX += 25;
}
}
void drawGameState3() {
}
void keyPressed() {
if (gameState1 == 1) {
if (keyCode == 32) {
gameState1 = 2;
}
}
else if(gameState1 == 2){
if(keyCode == RIGHT){
moveRight = true;
}
}
}
void keyReleased(){
if(keyCode == RIGHT){
moveRight = false;
}
}
I don't think you ever called drawPlayer1Movement(). Add it to keyPressed() and player1 should move to the right when you hit the right arrow.
void keyPressed() {
if (gameState1 == 1) {
if (keyCode == 32) {
gameState1 = 2;
}
} else if (gameState1 == 2) {
if (keyCode == RIGHT) {
moveRight = true;
drawPlayer1Movment();
}
}
}
How to solve this in Depth-First-Search:
6x6 squares, cut along the edges of the lattice into two parts.
The shape of the two parts is required to be exactly the same.
Try to calculate: There are a total of how many different segmentation methods.
Note: Rotational symmetry belongs to the same segmentation method.
For example:
Sorry, it looks like I'm just looking for an answer without thinking. Actually, I think a lot. The original title didn't require a Depth-First-Search, and I think it needs to be used to solve this problem, but I don't have a clear idea. I think that meet the requirements is between grid is continuous, but I don't know how to express this kind of situation.
I think the idea to use dfs is good. You could start the search on a clear (no walls) maze.
Start the search on an arbitrary cell.
For each cell explored : mark the symmetric one as "wall".
A pseudo code to find one segmentation could be:
boolean dfs(cell) {
if cell is not empty or was explores or null - return false
symCell = get Symetric Cell of cell
if symCell is not empty or was explores or null - return false
else mark symCell as wall
mark cell as explored
//loop over neighbors
for(Cell c : getNeighbors of cell){
if ( dfs(c) ) return true
}
return false
}
The process can be repeated over and over again to find more segmentations.
I did not come up yet with any good idea about a stop criteria: how do you know that all possible segmentations were found.
Here is a simple java swing demonstration of finding one segmentation:
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.GridLayout;
import java.awt.Point;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import javax.swing.BorderFactory;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
public class SwingMaze extends JFrame {
private JPanel mazePanel;
private Cell[][] cells;
private int mazeRows = 6, mazeCols = 6; //default size
public SwingMaze() { this(null); }
public SwingMaze(Cell[][] cells) {
this.cells = (cells == null) ?
getCells(mazeRows,mazeCols) : cells;
mazeRows = this.cells.length; mazeCols = this.cells[0].length;
setTitle("Grid");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
buildUi();
pack();
setVisible(true);
}
void buildUi() {
mazePanel = new JPanel();
mazePanel.setLayout(new GridLayout(cells.length, cells[0].length));
add(mazePanel, BorderLayout.CENTER);
for (Cell[] cellsRow : cells) {
for (Cell cell : cellsRow) {
cell.addMouseListener(cellMouseListener(cell));
mazePanel.add(cell);
}
}
add(new JLabel("Click any cell to set it origin and start search"),
BorderLayout.SOUTH);
}
private MouseListener cellMouseListener(Cell cell) {
return new MouseAdapter() {
#Override
public void mouseClicked(MouseEvent e) {solve(cell);}
};
}
private List<Cell> getNeighbors(Cell cell){
List<Cell> neighbors = new ArrayList<>();
for(int row = (cell.getPosition().x -1) ;
row <= (cell.getPosition().x +1) ; row++) {
if(! validPosition (row,0)) { continue;}
for(int col = (cell.getPosition().y -1) ;
col <= (cell.getPosition().y +1) ; col++) {
if(! validPosition (row,col)) { continue;}
if((row == cell.getPosition().x) &&
(col == cell.getPosition().y) ) { continue;}
if((row != cell.getPosition().x) &&
(col != cell.getPosition().y) ) { continue;}
neighbors.add(cells[row][col]);
}
}
Collections.shuffle(neighbors);
return neighbors;
}
private boolean validPosition(int row, int col) {
return (row >= 0) && (row < mazeRows)
&& (col >= 0) && (col < mazeCols);
}
private Cell getSymetricCell(Cell cell) {
if(! validPosition(cell.getPosition().x,
cell.getPosition().y)) { return null; }
int row = mazeRows - cell.getPosition().x -1;
int col = mazeCols - cell.getPosition().y -1;
return cells[row][col];
}
private Cell[][] getCells(int rows, int cols) {
Cell[][] cells = new Cell[rows][cols];
for(int row=0; row <cells.length; row++) {
for(int col=0; col<cells[row].length; col++) {
cells[row][col] = new Cell();
cells[row][col].setPosition(row, col);
}
}
return cells;
}
boolean solve(Cell cell) {
reset();
return dfs(cell);
}
boolean dfs(Cell cell) {
if(cell == null){ return false; }
//if cell is wall, or was explored
if( !cell. isToBeExplored()) { return false; }
Cell symCell = getSymetricCell(cell);
if((symCell == null) || ! symCell.isToBeExplored()) { return false; }
symCell.setState(State.WALL);
cell.setState(State.WAS_EXPLORED);
//loop over neighbors
for(Cell c : getNeighbors(cell)){
if (dfs(c)) { return true; }
}
return false;
}
private void reset() {
for(Cell[] cellRow : cells) {
for(Cell cell : cellRow) {
cell.setState(State.EMPTY);
}
}
}
public static void main(String[] args) {
new SwingMaze();
}
}
class Cell extends JLabel {
Point position;
State state;
private static int cellH =65, cellW = 65;
Cell() {
super();
position = new Point(0,0);
state = State.EMPTY;
setBorder(BorderFactory.createLineBorder(Color.RED));
setPreferredSize(new Dimension(cellH , cellW));
setOpaque(true);
}
boolean isToBeExplored() { return state == State.EMPTY; }
Point getPosition() {return position;}
void setPosition(Point position) {this.position = position;}
void setPosition(int x, int y) { position = new Point(x, y); }
void setState(State state) {
this.state = state;
setBackground(state.getColor());
}
State getState() { return state; }
#Override
public String toString() {
return "Cell " + position.getX() + "-" + position.getY()+ " " + state ;
}
}
enum State {
EMPTY (Color.WHITE), WALL (Color.BLUE), EXPLORED(Color.YELLOW),
WAS_EXPLORED(Color.PINK);
private Color color;
State(Color color) { this.color = color; }
Color getColor() { return color; }
}
Clicking will set it as origin and start search. Click the same cell again to see different segmentation.
I saw a way to solve this problem, which is to search from the line dividing the grid, the code is as follows:
public class Maze {
int point[][] = new int[10][10]; // The intersection between the line and the line
int dir[][] = {{-1,0},{1,0},{0,-1},{0,1}}; // get Neighbors
static int N = 6; // default size
static int count = 0;
public void dfs(int x, int y) {
if (x == 0 || y == 0 || x == N || y == N) {
count++;
return;
}
for(int i = 0; i < 4; i++) {
int n = x + dir[i][0];
int m = y + dir[i][1];
if (n < 0 || n > N || m < 0 || m > N) { continue; }
if (point[n][m] == 0) {
point[n][m] = 1;
point[N-n][N-m] = 1;
dfs(n, m);
point[n][m] = 0;
point[N-n][N-m] = 0;
}
}
}
public static void main(String[] args) {
Maze test = new Maze();
test.point[N/2][N/2] = 1; // Search from the center point
test.dfs(N/2, N/2);
System.out.println(count/4); // There are four types of rotational symmetry
} }
Making a space invaders knock off game. My code will not compile as I get the error message "It looks like you're mixing 'active' and 'static' modes", but I can not see where I am mixing them. Can someone please take a look at my code?
final int SCREENX=400;
final int SCREENY=400;
final int GAP=10;
final int ALIEN_ALIVE=0;
final int ALIEN_DEAD=6;
final int FORWARD=0;
final int BACKWARD=1;
final int MARGIN=30;
Alien theAliens[];
Bullet bullets[];
Player thePlayer;
void setup() {
PImage normalImg, explodeImg;
size(SCREENX, SCREENY);
normalImg =loadImage("invader.GIF");
explodeImg =loadImage("exploding.GIF");
theAliens = new Alien[10];
bullets = new Bullet[20];
init_aliens(theAliens, normalImg, explodeImg);
thePlayer = new Player(SCREENY- 50);
}
void init_aliens(Alien baddies[], PImage okImg, PImage
exImg) {
for (int i=0; i<baddies.length; i++) {
// This is buggy, what is the problem?
baddies[i] = new Alien(i*(okImg.width+GAP), 0, okImg,
exImg);
}
}
void init_bullets() {
for (int i = 0; i < bullets.size(); i++) {
Bullet b = (Bullet) bullets.get(i);
b.move();
b.draw();
}
}
void shoot() {
if (mousePressed)
Player.shoot();
}
void draw() {
background(0);
thePlayer.draw();
thePlayer.move(mouseX);
draw_bullets(myBullets);
for (int i=0; i<theAliens.length; i++) {
theAliens[i].move();
theAliens[i].draw();
if (random(0, 500)<1)
theAliens[i].die();
}
}
////// Player Class //////
Player() { ///** When I get the error, this line is highlighted**///
this.x = width/2;
this.y = height-50;
this.timeLastShot = 0;
this.coolDown = 200;
colour playColour= color(50);
void draw() {
fill(playerColour);
rect(this.x, this.y, 30, 30);
}
void move(int x) {
if (x>SCREENX-50)
xpos= SCREENX-50;
else xpos=x;
}
void shoot() {
if (millis() - timeLastShot > coolDown) {
Bullet bullet = new Bullet(this.x+12.5, this.y, -5);
bullets.add(bullet);
timeLastShot = millis();
}
}
}
Your Player class is badly written. It should be:
class Player {
Player () {
//constructor
}
void functionOfSorts () {
} // Never forget to enclose functions with curly brackets!
}
...As opposed to what you wrote:
Player() {
//yadayada
}
I have added logic to show the Sprite animating but it's simply not showing on the screen. What am I doing wrong?
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input.Touch;
namespace MyXNAGame.Game_Classes
{
public class Player : Sprite
{
private int _frameCount = 6;
private int _frameIndex;
private Rectangle[] _frames;
public float _jumpVelocity = 12f;
public PlayerState _playerState;
public Rectangle BoundingBox
{
get { return new Rectangle {X = (int) Position.X, Y = (int) Position.Y, Height = Texture.Height, Width = Texture.Width}; }
}
public void Initialize()
{
_frames = new Rectangle[_frameCount];
int width = Texture.Width / _frameCount;
for (int i = 0; i < _frameCount; i++)
{
_frames[i] = new Rectangle(i*width, 0, width, Texture.Height);
}
}
public void Load(ContentManager contentManager, string assetName)
{
Texture = contentManager.Load<Texture2D>(assetName);
}
public void Update(GameTime gameTime)
{
while (TouchPanel.IsGestureAvailable)
{
GestureSample gestureSample = TouchPanel.ReadGesture();
if (gestureSample.GestureType == GestureType.Tap)
{
if (_playerState == PlayerState.Running)
{
_playerState = PlayerState.NormalJump;
}
}
if (gestureSample.GestureType == GestureType.Hold)
{
if (_playerState == PlayerState.Running)
{
_playerState = PlayerState.LongJump;
}
}
}
// NormalJump Logic
switch (_playerState)
{
case PlayerState.NormalJump:
Position.Y -= _jumpVelocity;
_jumpVelocity -= 0.5f;
if (_jumpVelocity == 0)
{
_playerState = PlayerState.Falling;
}
break;
case PlayerState.LongJump:
Position.Y -= _jumpVelocity;
_jumpVelocity -= 0.5f;
if (_jumpVelocity == 0)
{
_playerState = PlayerState.Falling;
}
break;
case PlayerState.Falling:
Position.Y += _jumpVelocity;
_jumpVelocity += 0.5f;
break;
case PlayerState.Running:
_frameIndex++;
if (_frameIndex > 5)
{
_frameIndex = 0;
}
break;
}
}
public void Draw(SpriteBatch spriteBatch)
{
spriteBatch.Draw(Texture, Position, _frames[_frameIndex], Color.White, 0, new Vector2(0, 0), new Vector2(0, 0), SpriteEffects.None, 0);
}
}
}`
Can anyone see the obvious mistake? I am using WP7
I changed the 'Scale' parameter in the Draw() method from new Vector(0,0) to new Vector(1,1) as obviously, having a Scale of 0 will not show anything at all.
I basically want a character to walk in one direction for a while, stop, then go in another random direction. Right now my sprites look but don't move, randomly very quickly in all directions then wait and have another seizure. I will post the code I have so far in case that is useful.
class NPC: Mover
{
int movementTimer = 0;
public override Vector2 direction
{
get
{
Random rand = new Random();
int randDirection = rand.Next(8);
Vector2 inputDirection = Vector2.Zero;
if (movementTimer >= 50)
{
if (randDirection == 4)
{
inputDirection.X -= 1;
movingLeft = true;
}
else movingLeft = false;
if (randDirection == 1)
{
inputDirection.X += 1;
movingRight = true;
}
else movingRight = false;
if (randDirection == 2)
{
inputDirection.Y -= 1;
movingUp = true;
}
else movingUp = false;
if (randDirection == 3)
{
inputDirection.Y += 25;
movingDown = true;
}
else movingDown = false;
if (movementTimer >= 100)
{
movementTimer = 0;
}
}
return inputDirection * speed;
}
}
public NPC(Texture2D textureImage, Vector2 position,
Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize,
Vector2 speed)
: base(textureImage, position, frameSize, collisionOffset, currentFrame,
sheetSize, speed)
{
}
public NPC(Texture2D textureImage, Vector2 position,
Point frameSize, int collisionOffset, Point currentFrame, Point sheetSize,
Vector2 speed, int millisecondsPerframe)
: base(textureImage, position, frameSize, collisionOffset, currentFrame,
sheetSize, speed, millisecondsPerframe)
{
}
public override void Update(GameTime gameTime, Rectangle clientBounds)
{
movementTimer++;
position += direction;
if (position.X < 0)
position.X = 0;
if (position.Y < 0)
position.Y = 0;
if (position.X > clientBounds.Width - frameSize.X)
position.X = clientBounds.Width - frameSize.X;
if (position.Y > clientBounds.Height - frameSize.Y)
position.Y = clientBounds.Height - frameSize.Y;
base.Update(gameTime, clientBounds);
}
}
How about you create a method to get a random direction:
Vector2 GetRandomDirection()
{
Random random = new Random();
int randomDirection = random.Next(8);
switch (randomDirection)
{
case 1:
return new Vector2(-1, 0);
case 2:
return new Vector2(1, 0);
case 3:
return new Vector2(0, -1);
case 4:
return new Vector2(0, 1);
//plus perhaps additional directions?
default:
return Vector2.Zero;
}
}
And then, when a set time has elapsed, you call that method to change the direction:
double totalElapsedSeconds = 0;
const double MovementChangeTimeSeconds = 2.0; //seconds
public override void Update(GameTime gameTime, Rectangle clientBounds)
{
totalElapsedSeconds += gameTime.ElapsedGameTime.TotalSeconds;
if (totalElapsedSeconds >= MovementChangeTimeSeconds)
{
totalElapsedSeconds -= MovementChangeTimeSeconds;
this.direction = GetRandomDirection();
}
position += direction;
//...
}
Use different code to detect which direction the NPC is moving (the booleans movingLeft, movingRight, etc.). Detect those values based on the direction vector. This way you don't have to assign redundant values.
enum MoveDirection
{
Up, Down, Left, Right, UpLeft, UpRight, DownLeft, DownRight, None
}
public MoveDirection GetMoveDirection(Vector2 direction)
{
if (direction.Y < 0)
{
if (direction.X < 0)
return MoveDirection.UpLeft;
else if (direction.X > 0)
return MoveDirection.UpRight;
else
return MoveDirection.Up;
}
else if (direction.Y > 0)
{
if (direction.X < 0)
return MoveDirection.DownLeft;
else if (direction.X > 0)
return MoveDirection.DownRight;
else
return MoveDirection.Down;
}
else
{
if (direction.X < 0)
return MoveDirection.Left;
else if (direction.X > 0)
return MoveDirection.Right;
else
return MoveDirection.None;
}
}
I presume this is used for rotating the sprite (or perhaps drawing a different one), so now you just need a switch:
public override void Draw(GameTime gameTime, SpriteBatch spriteBatch)
{
MoveDirection moveDirection = GetMoveDirection(this.direction);
switch(moveDirection)
{
case MoveDirection.Up:
//Draw up-facing sprite, or assign a value to a rotation variable.
break;
case MoveDirection.UpLeft:
//...
}
}
You can examine Platformer Starter Kit to know how enemies move.
As Microsoft discontinue the XNA development for Windows 8, he removes all links to download XNA 4 starter kits.
I upload original Platformer source code to bitbucket.
Here you can download original Platformer Starter Kit Source Code for XNA 4 http://vackup.blogspot.com.ar/2012/11/download-original-platformer-starter.html