Adding a new player with keys WASD - java

I am really new to programming. For my class, I am making a game and I would like to add a seconds player to the game. At the moment, there are black circles that appear randomly in the game and keep growing. You are a circle and you need to avoid the circles for as long as possible. Once you intersect with one the game ends. This circle is controlled with the arrow keys. However I would like to add a new circle with the keys WASD. This is my code so far. But when the game starts I can see the circle but I cannot move it.
The main part of the code I am worried about is ProcessUserInput2 because that is the code that controls WASD. I have not pasted in my entire code. Any help would be much appreciated
void draw()
{
//Call functions
if (gameState == 0)//Start Screen
{
ProccessUserInput_Start(); //this function is in a separate tab. It processes what the player inputs into the computer, and then translates it into commands
Render_Start();
savedTime = millis();
}
if (gameState == 1)//Game Playing Screen
{
ProcessUserInput1(); //this is for the arrow keys
ProcessUserInput2(); //this is for WASD
Render();
totalTime = 40000; //Timer (in millis)
for (growingEllipse e:ellipses)
{
e.ellipseGrow();
e.rendering();
}
void ProcessUserInput1()
//Move circle Left, Right, Up or Down using arrow keys
{
if (keyPressed)
{
if (keyCode == LEFT)//Move Left
{
x1 = x1 - 2;
}
if (keyCode == RIGHT)//Move Right
{
x1 = x1 + 2;
}
if (keyCode == UP)//Move Up
{
y1 = y1 - 2;
}
if (keyCode == DOWN)//Move Down
{
y1 = y1 + 2;
}
}
}
void ProcessUserInput2()
//Move circle Left, Right, Up or Down using arrow keys
{
if (keyPressed)
{
if (keyCode == 'A')//Move Left
{
x2 = x2 - 2;
}
if (keyCode == 'D')//Move Right
{
x2 = x2 + 2;
}
if (keyCode == 'W')//Move Up
{
y2 = y2 - 2;
}
if (keyCode == 'S')//Move Down
{
y2 = y2 + 2;
}
}
}
void Render()
{
background(255);
fill(255, 228, 196);
ellipse (x1, y1, r1, r1);
ellipse (x2, y2, r1, r1);
//draw circle for player
}
If possible, could any really good programmers give me their email so that I can ask them questions? I still need to add in a few more items such as inheritance and function overloading. I used the Processing application for this.

You're using the keyCode variable, which only works with things like the arrow keys that don't have associated characters.
Instead, you might want to use the key variable, which is a char and contains the character typed.
More info here: http://staticvoidgames.com/tutorials/intermediateConcepts/keyboardInput
Edit: Also, as Jordi said, you're only catching upper-case letters. And please don't ask for email, as that defeats the whole point of public sites like this.

Related

Java smooth movement with KeyEvents in breakout

I'm currently learning Java through Stanford's Programming Methodology (2008) course. I'm trying to create the game Breakout and am trying to currently animate the paddle, which is a GRect type object. Here's my code:
// moves paddle via keyboard
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_RIGHT && paddle.getX() < getWidth() - paddle.getWidth()) {
paddle.move(5, 0);
}
if (key == KeyEvent.VK_LEFT && paddle.getX() > 0) {
paddle.move(-5, 0);
}
}
//moves paddle via mouse
public void mouseMoved(MouseEvent e) {
while (e.getX() > paddle.getX() + PADDLE_WIDTH/2 && paddle.getX() < getWidth() - PADDLE_WIDTH) {
paddle.move(1, 0);
}
while (e.getX() < paddle.getX() + PADDLE_WIDTH/2 && paddle.getX() > 0) {
paddle.move(-1, 0);
}
The problem is, if I move the paddle with mouse, it follows just fine, it's much smoother than when I try to move it with keyboard. Changing the values in move() method only changes the speed at which the paddle moves.
I've tried googling and one of the things people do is to gradually increase and decrease the speed at which the paddle moves, but I'm not sure how to implement that correctly through this library. Here's my attempt:
private double acceleration(double finalSpeed) {
if (finalSpeed > initialSpeed) {
initialSpeed += delta;
} else if (finalSpeed < initialSpeed) {
initialSpeed -= delta;
}
return initialSpeed;
}
private double initialSpeed = 0;
private double delta = 0.5;
After this I just set the paddle.move(acceleration(5),0) instead of paddle.move (5,0). And I've also added the KeyReleased method that sets the speed to the initial value:
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_RIGHT || key == KeyEvent.VK_LEFT) {
initialSpeed = 0;
}
However, the movement of the paddle when I switch between left and right arrow keys is not responsive. It has about 0.5 sec delay to start moving the other direction, I've spend whole day trying to figure out the solution but to no avail. Please give me any tips, thanks!
It seems that there's some problem with the threads (which I don't fully understand). Doing this helped:
Instead of moving the paddle directly with listeners, I created two booleans: left_key_downand right_key_down and set them to true if corresponding key was pressed. After that I moved the paddle using: if (left_key_down) move (-5,0) And similarly with right motion. This resulted in smooth motion.

Make my rectangle randomly fall down from my screen?

I am trying to make a game and am almost done with the code. But I can't make my rectangle randomly fall down from my screen.
I am coding a car game that is supposed to dodge the other cars. But is not working. can someone help me?
int carx = 200;
int cary = 0;
float speedx = 0;
float speedy = 0;
float accy = 0.1;
color rod = color(255, 0, 0);
color vit = color(255);
final int START_STATE = 1;
final int PLAY_STATE = 2;
final int GAMEOVER_STATE = 3;
final int RESTART = 4;
int state = START_STATE;
void setup() {
size(400, 700);
}
void draw() {
switch (state) {
case START_STATE:
drawStart();
break;
case PLAY_STATE:
drawPlay();
break;
case GAMEOVER_STATE:
drawGameOver();
case RESTART:
drawrestart();
}
}
void init() {
carx = 200;
cary = 0;
speedx = 0;
speedy = 0;
accy = 0.1;
}
void drawStart() {
background(0);
textAlign(CENTER, CENTER);
textSize(16);
text("Click the mouse button to start the game", width / 2, height / 2);
if (mousePressed) {
state = PLAY_STATE;
}
}
void drawGameOver() {
textAlign(CENTER, CENTER);
textSize(20);
text("you have crashed your car", width / 2, height / 2);
if (mousePressed) {
state = PLAY_STATE;
init();
}
}
void drawrestart() {
textAlign(CENTER, CENTER);
textSize(15);
text("press mouse to restart", 200, 400);
if (keyPressed) {
state = RESTART;
}
}
void drawPlay() {
background(0);
if (get(carx, cary) == vit) {
speedy = -1 * speedy;
}
fill(rod);
rect(carx, cary, 50, 30);
if (get(mouseX, 600) == color(255, 0, 0)) {
state = GAMEOVER_STATE;
}
fill(#FFFFFF);
rect(mouseX, 600, 30, 50);
carx += speedx;
cary += speedy;
speedy += accy;
}
The code you have at the moment only has one rectangle fall down from the top for each 'round' of the game. I'm not sure if you wanted to have multiple blocks falling; I think that would be a good next step.
For now, here's a simple hack which will cause the block to fall from a random position each time, like you requested.
At the very start of your code, outside of the functions, place:
boolean randomise;
Then, within void init() you should add:
randomise = true;
Finally, add this section into drawPlay(), right at the start of the function:
if (randomise){
carx = int(random(width-50));
randomise = false;
}
Note that a new random x co-ordinate will only generate every time you set the boolean 'randomise' to true again. So if you generate a new iteration with more than one block falling inside the drawPlay() function, you should bear this in mind and adjust the code accordingly.
------- [EDIT] -------
Hi, glad that this helped.
I've actually noticed another little issue which I will help you fix.
Currently, you are checking at mouseX to see whether there has been a collision. This works (mostly), but if the right side of the player's white car drives through the left edge of a red falling block, then the game continues as though nothing has happened. What should occur is that the game is over because a collision is detected. You want to find out if any part of the two shapes have overlapped.
To do this, you should alter the code like so. In drawPlay(), replace:
if (get(mouseX, 600) == color(255, 0, 0)) {
state = GAMEOVER_STATE;
}
with:
if (get(mouseX, 600) == color(255, 0, 0) || get(mouseX + 30, 600) == color(255, 0, 0)) {
state = GAMEOVER_STATE;
}
This is an OR statement - checking whether either side of the player's car has collided. This way, every time they bump into each other, the game will end.
Now for your question: how to add multiple cars?
There are a few ways you could go about this, but I'll show you the most straightforward.
In drawPlay(), you want to add this little if statement:
if (cary > height){
init();
}
Basically what we're doing here is checking if the previous red block/car has fallen off the bottom of the sketch. If it has, i.e. if the red block's y co-ordinate is larger than the height of the whole sketch, we call init() again. This will reset everything, including making randomise true. Once randomise is true, the previous code you added will select a random start point for the block, and it will fall all over again.
I hope you've understood everything I explained - whilst my code will fix your problem, the best way to learn is to try to solve things by yourself. Check out Dan Shiffman's videos on YouTube. These are a great starting place to get to grips with Processing - hopefully you'll be more confident writing your own code after following along with his examples :)
Use random to generate a random x coordinate:
carx = (int)random(0, width-50);
Reset the position and the speed of the care, once the car reached to bottom of the window:
void drawPlay() {
if (cary > height) {
carx = (int)random(0, width-50);
cary = 0;
speedy = 0;
}
// [...]

Multiple classes in processing

I'm making a game where you're controlling a square, and objects will spawn in random places, which you have to pick up to get points, while also having to dodge big squares going from side to side. Right now I have 2 classes (one for enemies - big squares -, and one for the hero), I haven't done the point system yet with the spawning objects, but that's not what I'm trying to do now.
So my problem right now is that I don't really know how to make the person lose the game/a life when you touch the "enemies" with your hero. I would know how to do it without classes, but I'd like to know how to do it when they are in separate classes.
If someone could explain with code and comments how this would be done, it would help me out a lot :) (I read something about 'extends' for classes but I'm not sure if this is what I should use or not).
Here's a screenshot of what my game looks like at the moment, just to better illustrate it:
Here's the main code page:
Hero myHero = new Hero(400,480,5);
Enemies myEnemies = new Enemies(50,50,10);
Enemies myEnemies2 = new Enemies(50,350,15);
Enemies myEnemies3 = new Enemies(50,650,12);
void setup() {
size(900,800);
frameRate(30);
smooth();
}
void draw() {
background(0);
myHero.keyPressed();
myEnemies.enemyDisplay();
myEnemies.enemyMove();
myEnemies2.enemyDisplay();
myEnemies2.enemyMove();
myEnemies3.enemyDisplay();
myEnemies3.enemyMove();
}
Class 1:
class Enemies {
float xpos, ypos, speed;
Enemies(float x, float y, float s) {
xpos = x;
ypos = y;
speed = s;
}
void enemyDisplay() {
rect(xpos, ypos, 100, 100);
}
void enemyMove() {
xpos += speed;
if((xpos > width - 100) || (xpos < 0)) {
speed *= -1;
}
}
}
Class 2:
class Hero {
float xpos_, ypos_, speed_;
Hero(float x, float y, float s) {
xpos_ = x;
ypos_ = y;
speed_ = s;
}
void keyPressed() {
if (key == CODED) {
if (keyCode == UP) {
ypos_ -= speed_;
}
if (keyCode == DOWN) {
ypos_ += speed_;
}
if (keyCode == LEFT) {
xpos_ -= speed_;
}
if (keyCode == RIGHT) {
xpos_ += speed_;
}
}
rect(xpos_,ypos_,30,30);
}
}
I believe the question you are asking involves basic collision detection and object interactions.
I would first make the Enemies a List and create it / add elements during the setup() call:
List<Enemies> enemies = new List<Enemies>();
enemies.add(new Enemies(50,50,10));
This allows you to store all of your Enemies under one object. So your draw() method would look something like:
void draw(){
background(0);
myHero.keyPressed();
for(Enemies enemy : enemies)
{
enemy.enemyDisplay();
enemy.enemyMove();
if (hero.isCollidingWith(enemy)) // collision method defined in the hero object, but you could define it in the Enemies class as well, it doesn't really matter
{
hero.removeHealth(); // method defined in hero that removes health
}
}
}
This method would be in one of your classes:
public boolean isColliding(Enemies enemy)
{
// check the x and y coordinates of each object
}
I hope this helps to point you in the right direction.
you need to figure out collision detection and when your objects collide with each other, something basic like:
class Enemy
{
//...
public boolean isColliding(Hero hero)
{
//figure out the distance between two objects, if its less than their size, they are colliding..
//...
}
//...
}
then you need a part of your Game Loop that checks if anything is colliding with your hero, pickups, walls, etc...
It seems the first part you need help with is collision detection. The short answer I would give that will almost undoubtedly lead you to more questions is to look at the Area class (specifically Area.intersect). You might also want to look at the classes I've put together for displaying & managing areas in this project here
There are several problems here that touch on both application design as well as conventions. These should be addressed first before trying to tackle the collision detection problem.
The Enemies class only represents a single enemy, so the name of the class should reflect that. Additionally, prefixing the method names with "enemy" is redundant and can be removed. Other changes have been commented in the revised class below.
public class Enemy {
// Instead of hard-coding in the width and height of an enemy, allow the
// instantiating code to specify the enemy's size. This will allow you
// to have different size enemies and prevents you from having "magic numbers"
// in your code.
private float xpos, ypos, width, height, speed;
public Enemy(float x, float y, float s, float w, float h) {
xpos = x;
ypos = y;
width = w;
height = h;
speed = s;
}
/* These getters will be used for collision detection later */
public float getX() {
return xpos;
}
public float getY() {
return ypos;
}
public float getWidth() {
return width;
}
public float getHeight() {
return height;
}
// I've changed `display` to `draw` to be consistent with the method name in
// your main `draw` method.
public void draw() {
rect(xpos, ypos, width, height);
}
// This method now accepts a screenWidth parameter so that the enemy can know
// when they've collided with the left or right wall of the screen without
// having to rely on an global variable.
public void move(int screenWidth) {
xpos += speed;
if ((xpos > screenWidth - width) || (xpos < 0)) {
speed *= -1;
}
}
}
I mention the "magic numbers" in one of the comments above. See this wikipedia article for more on that.
The Hero class contains property names that have an underscore postfix. This ranges from unconventional to inconsistent with respect to all of your other property names in your other classes. The original keyPressed() method mixes the logic for both drawing and moving. These two things have been separated and the methods named like those of the Enemy class for consistency.
public class Hero {
private float xpos, ypos, width, height, speed;
public Hero(float x, float y, float s, float w, float h) {
xpos = x;
ypos = y;
width = w;
height = h;
speed = s;
}
// Change this method name to draw for consistency with the Enemy class
public void draw() {
// Key press functionality has been moved to the `move` method for consistency
// with the Enemy class.
rect(xpos, ypos, WIDTH, HEIGHT);
}
// This method uses the variables key, keyCoded, UP, DOWN, LEFT, and RIGHT. You
// did not include any import statements with your code, so they may be coming
// from there; however, if they are globals, you should pass them to this method
// as arguments whenever you call it.
public void move() {
// If this condition isn't satisfied, return immediately. This prevents
// unnecessary nesting and work below.
if (key != CODED) {
return;
}
if (keyCode == UP) {
ypos -= speed;
}
// Use `else if` here and below to prevent multiple unnecessary
// comparisons of keyCode.
else if (keyCode == DOWN) {
ypos += speed;
}
else if (keyCode == LEFT) {
xpos -= speed;
}
else if (keyCode == RIGHT) {
xpos += speed;
}
}
public boolean isColliding(Enemy enemy) {
// Collision detection is easy since all of your game entities (the hero and
// the enemies) are all rectangles and axis-aligned (not rotated). You can
// use a method known as "bounding box intersection."
return (Math.abs(enemy.getX() - xpos) * 2 < (enemy.getWidth() + width))
&& (Math.abs(enemy.getY() - ypos) * 2 < (enemy.getHeight() + height));
}
}
For more on bounding box intersection, see this gamedev stackexchange question.
Now that your classes are in order, its time to address your main code. We'll need to update the method names and, as #James T suggested, you should make a list of enemies instead of creating a new independent object for each enemy. This will make it easier for you to add or remove enemies in the future and to be able to process all enemies with one block of code without repeating yourself.
// Use constants to remove magic numbers.
private static final int SCREEN_WIDTH = 900;
private static final int SCREEN_HEIGHT = 800;
private Hero myHero = new Hero(400, 480, 30, 30, 5);
private List<Enemy> enemies = new ArrayList<Enemy>();
void setup() {
size(SCREEN_WIDTH, SCREEN_HEIGHT);
frameRate(30);
smooth();
enemies.add(new Enemy(50, 50, 100, 100, 10));
enemies.add(new Enemy(50, 350, 100, 100, 15));
enemies.add(new Enemy(50, 650, 100, 100, 12));
}
void draw() {
hasCollision = false;
background(0);
// I've changed the order of draw->move to move->draw. If you draw first, then
// move, then detect collisions, it will appear to your user that your hero has
// not yet collided with an enemy even though you act as they have (e.g.: they
// will not see the collision until the next time you draw the scene).
myHero.move();
myHero.draw();
for (Enemy enemy : enemies) {
enemy.move();
enemy.draw(SCREEN_WIDTH);
if (!hasCollision && myHero.isColliding(enemy)) {
hasCollision = true;
}
}
if (hasCollision) {
// Handle enemy collision here
}
}
You'll notice that I've also added accessibility modifiers to everything. While it is technically valid to exclude them and use the defaults, it makes your code more readable to include them because it is more obvious. When you're first starting out, the more obvious the better.
Alright got it to work thanks to all you helpful wonderful people!
I did this:
public boolean isColliding(Enemies h){
float distance = dist(x,y,h.x,h.y);
if(distance<100){
return true;
}else{
return false;
}
}
and in my draw(){ I have
if(myHero.isColliding(myEnemies)){
println("You lost!");
}
I had a very similar 'fix' earlier, but the reason I got an error was because I had Hero h instead of Enemies h in the 'if' function, so it was just a very dumb error that I overlooked :P

java - collision detection not working?

im quite new to java. I am trying to make it so that i can control a ball with the arrow keys and then if you collide with another ball, it will print a line in the console saying "you lost" or somthing.
I have done the moving, but i am struggling a bit with how i can get the 2 balls to collide. so far i have tried this (i think i put a rectangle around the ball, but i don't know really!):
public void collision() {
Rectangle rectP = new Rectangle(player.x, player.y, player.WIDTH, player.HEIGHT);
Rectangle rectE = new Rectangle(Enemy.ex, Enemy.ey, Enemy.WIDTH, Enemy.HEIGHT);
if(rectP.intersects(rectE))
{
System.out.println("game over");
}
}
Could someone help me out and explain what i have done wrong.
ps. please don't just give me the code, i do want to try and learn!!!.
thanks.
public void actionPerformed(ActionEvent e) {
repaint();
x += velx;
y += vely;
}
public void up() {
vely = -1.5;
velx = 0;
}
public void down() {
vely = 1.5;
velx = 0;
}
public void left() {
vely = 0;
velx = -1.5;
}
public void right() {
vely = 0;
velx = 1.5;
}
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
if (code == KeyEvent.VK_UP) {
up();
}
if (code == KeyEvent.VK_DOWN) {
down();
}
if (code == KeyEvent.VK_LEFT) {
left();
}
if (code == KeyEvent.VK_RIGHT) {
right();
}
}
If you have coords X and Y of the two ball centers and you know balls radiuses - this should be a simple task.
Just calculate the distance between centers of the balls and compare it with sum of balls radiuses.
You asked to skip formulas so that's it :)
PS What looks strange in your code is that player is lowercased but Enemy is capitalized.. is it a class or an object?
Well, I don't think that what is wrong is the collision detection. I think that what is wrong is that what the computer think that the objects are somewhere else then where they actually are. Like one time when I was trying to make a brickbreaker paddle, I was having problems with collision detection when really the program thought that the paddle was on the opposite side! What you should do is that you should draw the positions of the rectangle onto the game. This way, you can see where the computer thinks the objects are. Maybe they are totally off?

How to do collision detection with many walls (maze)?

In my game, the player navigates a maze. I can't figure out how to do proper collision detection with the walls. It is easy to do collision detection for staying in a certain area:
if (x > rightWallX - playerWidth) x = rightWallX - playerWidth;
if (x < leftWallX) x = leftWallX;
//...
But how would I do collision detection for many walls?
I can do plain collision detection without correction (like if (intersecting) return true;), but I can't correct this correctly. If I just store the old x and y and reset them, then
The object never actually touches the wall
If the object can go up but is blocked to the right, it won't go up, it will just not move.
How is collision detection in a maze done?
The easiest way, once you have solved collision detection, to fix the collision is to move the actor to the closest valid position to where the actor would be were it not for the object it collides with. This assumes no inertia, but it is sufficient for maze-like games or top-down map-crawling games.
If you want to simplify your calculations further, you can limit yourself to detecting if changing the actor's x or y coordinate would be better. If your actor has an axis-aligned rectangular hit-box and all obstacles are axis-aligned rectangular as well (the simplest case), this assumption is indeed correct. However, the results might not be satisfactory in some other cases (potential artifact: speed boost from gliding diagonal walls - not the case in most maze games).
Keep in mind multiple collisions could happen concurrently (pushing against two walls). If there are no sharp angles between two walls that an actor could both intersect (say, if all your obstacles are axis aligned and sufficiently spaced), fixing each collision in turn will suffice - just don't stop after the first collision.
You can use Rectangle.intersects() method:
public Rectangle Player(){
return new Rectangle(PlayerX,PlayerY,PlayerWidth,PlayerHeight);
//we do this for getting players x and y values every tick
}
if(Player().intersects(new Rectangle(0,0,100,50)))//if(player touching wall)
new Rectangle(0,0,100,50) is just an example you can change it.
Ok so i'm currently making a 2D top down view game and I'm not sure how you created your maze. However, in my game my Level is created from a Tile[][] tiles = new Tile[levelWidth][levelHeight]; array. The way i handled collision detection was by checking the surrounding tiles to see if they were solid.
This is my getTile method.
public Tile[][] getTile(int x, int y) {
if (x < 0 || x >= getWidth() || y < 0 || y >= getHeight()) {
return new VoidTile();
} else {
return tiles[x][y];
}
}
In my Tile.java class i have a isSolid() method which returns whether the tile is solid or not. All of my tiles extend my Tile.java so they inherit this method and I override it in their constructor. As i said previously, I am not sure whether or not you use the same style of level implementation as i do. However, It is good practice to do it this way :)
Personally, I am not a big fan of using the .intersects() and .contains() methods for Sprite collision detection. I mainly use them for buttons and alike.
Ok so,
In my player.java class i have a checkBlockedDirection(int x, int y) method and it looks like this.
public void checkBlockedDirection(int x, int y) {
boolean u = map.getTile(x, y - 1).isSolid();
boolean d = map.getTile(x, y + 1).isSolid();
boolean l = map.getTile(x - 1, y).isSolid();
boolean r = map.getTile(x + 1, y).isSolid();
if (u) {
uBlocked = true;
System.out.println("up tile blocked");
} else {
uBlocked = false;
}
if (d) {
dBlocked = true;
System.out.println("down tile blocked");
} else {
dBlocked = false;
}
if (l) {
lBlocked = true;
System.out.println("left tile blocked");
} else {
lBlocked = false;
}
if (r) {
rBlocked = true;
System.out.println("right tile blocked");
} else {
rBlocked = false;
}
}
Then in my player update method i have this
public void tick() {
float dx = 0;
float dy = 0;
if (input.up.isPressed()) {
direction = 0;
} else if (input.down.isPressed()) {
direction = 2;
} else if (input.left.isPressed()) {
direction = 3;
} else if (input.right.isPressed()) {
direction = 1;
} else {
direction = 4; // standing
}
checkBlockedDirection((int)x, (int)y);
if (input.up.isPressed() && y > 0 && !uBlocked) {
dy += -speed;
} else if (input.down.isPressed() && y < map.getHeight() - 1 && !dBlocked) {
dy += speed;
} else if (input.left.isPressed() && x > 0 && !lBlocked) {
dx += -speed;
} else if (input.right.isPressed() && x < map.getWidth() - 1 && !rBlocked) {
dx += speed;
}
x += dx;
y += dy;
}
Basically it just checks whether or not the blocks up, down, left, or right are solid. If they are solid then it wont move and if they arent solid then you can move in the desired direction.
Not sure if this helps or not but it's just my take on this kind of grid collision detection :)
Hope this helps :)
Enjoy

Categories

Resources