I have already got the jumping on the y-axis running fine, but I want to be able to use 'dx' from jumping while pressing the left/right key (ex. if I am pressing right key to go right and jump while still holding it, the character will move in a "diagonal" way)
My main jumping code (timer activated when jump key is pressed):
public void actionPerformed (ActionEvent e) {
dy += 1;
y_pos += dy;
if (y_pos >= 400) {
dy = 0;
y_pos = 400;
timer.stop();
}
repaint();
}
Now my KeyEvent code:
if (command == KeyEvent.VK_RIGHT){
x_pos += 5;
right = true;
}
if (command == KeyEvent.VK_LEFT) {
x_pos -= 5;
right = false;
}
if (command == KeyEvent.VK_UP) {
if (!(timer.isRunning()))
dy = -20;
timer.start();
}
dr.repaint();
Below is how I would implement the input logic. Note that there are several choices when you want to dig further into input handling. Using this implementation, keyboard inputs are separated from the effects they have on the game world, which is handy in several ways. For example, the speed of the character is constant (given the timing of the game loop / movements is handled correctly) regardless of the frequency of key presses / repeats.
Anyway, some pseudo code:
// Global:
array keysdown;
keysdown[left] = false;
keysdown[right] = false;
keysdown[up] = false;
// The all-important game loop:
while (true) {
pollInputs();
doMovement();
draw();
}
function pollInputs () {
foreach (key that you want to handle) {
if (key.state == down) {
keysdown[key] = true;
} else {
keysdown[key] = false;
}
}
}
function doMovement () {
if (keysdown[left]) {
// move character left
} else if (keysdown[right]) {
// move character right
}
if (keysdown[up]) {
// initiate jump
}
}
Related
I understand the basis of collision detection and have developed my way (as far as I know) for collision detection. However, it does not seem to be working. What I have done is instead of drawing full rectangles around sprites, shapes, and other objects, I simply made methods that draw lines (very thin rectangles) on all sides of the object, left, right, top, and bottom.
The methods that draw the thin rectangles on the left,right,top, and bottom of the specified sprites. This is probably not the best way to do collision, but this is what I have, and am open to all ideas and different solutions!
Note: The(int)(x-Game.getCamera().getX()),(int)(y + height -Game.getCamera().getY()), is simply for the camera, so when the player moves, the trees (in my case the object I want to collide with) do not move with him
public Rectangle getBounds() {
return new Rectangle((int)(x-Game.getCamera().getX()),
(int)(y + height - Game.getCamera().getY()),width,height-height);
}
public Rectangle getBoundsTop() {
return new Rectangle((int)(x-Game.getCamera().getX()),
(int)(y- Game.getCamera().getY()),width,height-height);
}
public Rectangle getBoundsRight() {
return new Rectangle((int)(x + width -Game.getCamera().getX()),
(int)(y - Game.getCamera().getY()),width - width,height);
}
public Rectangle getBoundsLeft() {
return new Rectangle((int)(x -Game.getCamera().getX()),
(int)(y- Game.getCamera().getY()),width - width,height);
}
Actual collision CHECKING (in player class)-
if(getBounds().intersects(treeTile.getBoundsTop())) {
//What happens when they collide
//When the bottom of the player collides with the top of the tree.
}
if(getBoundsTop().intersects(treeTile.getBounds())) {
//What happens when they collide
//When the top of the player collides with the bottom of the tree
}
if(getBoundsRight().intersects(treeTile.getBoundsLeft())) {
//What happens when they collide
//when the right side of the player collides with the left of the
//tree
}
if(getBoundsLeft().intersects(treeTile.getBoundsRight())) {
//What happens when they collide
//When the left of the player collides with the right of the tree
}
I appreciate all the help I can get
Here is collision and movement code-
for (int i = 0; i < handler.object.size(); i++) {
Square handle = handler.object.get(i);
if (getBounds().intersects(treeTile.getBoundsTop())) {
handle.setvelY(-1);
}
if (getBoundsTop().intersects(treeTile.getBounds())) {
handle.setvelY(0);
}
if (getBoundsRight().intersects(treeTile.getBoundsLeft())) {
handle.setvelX(0);
}
if (getBoundsLeft().intersects(treeTile.getBoundsRight())) {
handle.setvelX(0);
}
}
Movement-
public void keyPressed(KeyEvent e) {
int code = e.getKeyCode();
for (int i = 0; i < handler.object.size(); i++) {
Square handle = handler.object.get(i);
if (handle.getId() == ObjectId.Zelda) {
if (code == KeyEvent.VK_D) {
handle.right();
}
if (code == KeyEvent.VK_A) {
handle.left();
}
if (code == KeyEvent.VK_W) {
handle.up();
}
if (code == KeyEvent.VK_S) {
handle.down();
}
}
My new collision idea -
boolean walkRight = true;
boolean walkLeft = true;
boolean walkDown = true;
boolean walkUp = true;
public void tick() {
if(walkRight == true) {
velX = 2;
}if(walkLeft == true) {
velX = -2;
}if(walkDown == true) {
velY = 2;
}if(walkUp == true) {
velY = -2;
}
if (getBounds().intersects(treeTile.getBoundsTop())) {
walkDown = false;
}
if (getBoundsTop().intersects(treeTile.getBounds())) {
walkUp = false;
}
if (getBoundsRight().intersects(treeTile.getBoundsLeft())) {
walkRight = false;
}
if (getBoundsLeft().intersects(treeTile.getBoundsRight())) {
walkLeft = false;
}
Something like this, not exactly, it is just an example.
Have you tried using 1 instead of width - width and height - height ?
I think these evaluating to 0 for the width / height is causing the intersects function to fail.
EDIT
I think you're over complicating this. If you just have one big collision box, instead of four small ones, then where ever you're moving your player, you can
// Square previousPosition = currentPosition
// do move player code, which presumably updates the currentPosition
// loop through all the trees you have
// if the player is colliding with a tree
// currentPosition = previousPosition
This should handle the player colliding with any side of the tree, since we just move them back to where they were previously.
I have a moving image as a background
PImage background;
int x=0; //global variable background location
rocket Rocket;
void setup(){
size(800,400);
background = loadImage("spaceBackground.jpg");
background.resize(width,height);
Rocket = new rocket();
}
void draw ()
{
image(background, x, 0); //draw background twice adjacent
image(background, x+background.width, 0);
x -=4;
if(x == -background.width)
x=0; //wrap background
Rocket.defender();
Rocket.move();
}
In a different class i'm trying to make a rocket move up and down
class rocket {
float x;
float y;
float speedy;
boolean up;
boolean down;
rocket(){
x = 50;
y = 200;
speedy = 3;
}
void move() {
if(up)
{
y = y - speedy;
}
if(down)
{
y = y + speedy;
}
}
void defender(){
fill(255,0,0);
rect(x,y,50,20);
triangle(x+50,y,x+50,y+20,x+60,y+10);
fill(0,0,100);
rect(x,y-10,20,10);
}
void keyPressed(){
if(keyCode == UP)
{
up = true;
}
if(keyCode == DOWN)
{
down = true;
}
}
void keyReleased(){
if(keyCode == UP)
{
up = false;
}
if(keyCode == DOWN)
{
down = false;
}
}
}
The rocket will display but won't move. I tried everything I know but nothing works. I also tried the rocket class just as a project by itself and the rocket moves, so it has to be something with the class. i'm quite new to coding so please keep that in mind, thank you in advance.
The keyPressed() and keyReleased() functions (and any other event function) need to be at the sketch level, not inside another class. If they're inside another class, Processing doesn't know how to find them.
So, what you need to do is move the keyPressed() and keyReleased() functions to the sketch, and then call functions on your Rocket class (class names should start with an upper-case letter, btw), similar to how you're calling rocket.defender() and rocket.move() (variable names should start with a lower-case letter) from the sketch-level draw() function.
I am making a java 2d side scroller and im having problems with multiple keys at the same time. Such as right + up. Whenever you release the up you stop moving right as you slowly go back to the ground even though right is still being pressed. Here are the keyboard listeners I have setup. dx is my horizontal movement speed and dy is the vertical height. Below is from the character class
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
dx = -5;
mainCharacterImageFacing = l.getImage();
}
if (key == KeyEvent.VK_RIGHT) {
dx = 5;
mainCharacterImageFacing = r.getImage();
}
if (key == KeyEvent.VK_UP) {
dy = 1;
mainCharacterImageFacing = r.getImage();
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT);
dx = 0;
if (key == KeyEvent.VK_RIGHT)
dx = 0;
if (key == KeyEvent.VK_UP)
{dy = 0;
mainCharacterImageFacing = r.getImage();
}
This is some code from the main game window that deals with calling the key press/release methods as well as dealing with the jump.
private class AL extends KeyAdapter{
public void keyReleased(KeyEvent e) {
p.keyReleased(e);
}
public void keyPressed(KeyEvent e) {
p.keyPressed(e);
}
}
#Override
public void run()
{
long beforeTime;
long timeDiff;
long sleep;
beforeTime = System.currentTimeMillis();
while(done == false)
{
cycle();
timeDiff = System.currentTimeMillis() - beforeTime;
sleep = 10 - timeDiff;
if (sleep < 0 )
sleep = 2;
try {
Thread.sleep(sleep);
} catch (Exception e)
{}
beforeTime = System.currentTimeMillis();
}
done = false;
h = false;
k = false;
}
boolean h = false;
boolean done = false;
public void cycle() {
if (h == false)
v = v - 2; //jump speed falling
if (v == 350) //max y value of jump. Lower numbers = higher jumps
h = true;
if (h == true && v <= 470) //starting y value
{
v = v + 2; //jump speed rising
if (v == 470)
done = true;
}
}
Do not handle your movement directly in the AL class. Instead, use booleans and set them to true/false accordingly:
private class AL extends KeyAdapter{
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT) {
left = true;
}
if (key == KeyEvent.VK_RIGHT) {
right = true
}
if (key == KeyEvent.VK_UP) {
//...
}
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
if (key == KeyEvent.VK_LEFT)
left = false
if (key == KeyEvent.VK_RIGHT)
right = false
if (key == KeyEvent.VK_UP)
//...
}
}
The reason for this is because keyPressed and keyReleased are called when the keys are acted upon, though that means it will not be in sync with your main loop.
To move your sprite call a method in the loop which, if your conditions are true, moves your sprite accordingly, else does nothing.
EDIT: After reviewing your code some more I have a few suggestions.
First of all, look up sub-pixel rendering. Sub-pixel rendering is used to make the movement of sprites look smoother.
Another thing to look up is variable timesteps (sometimes referred to as delta timesteps). Delta time can be used to make sure that actions are performed in sync with a players fps. If one player has 60fps and another has 30fps, the player with 30fps will see actions performed at half the speed. With a delta timestep however, actions are always performed at the same speed. Here's a good article.
The third thing is your timing. Currently you're using System.getCurrentTimeMills. This is bad, and not precise. Instead, use System.nanoTime.
A fourth thing I've spotted is your jumping algorithm. A better way is to include acceleration. First you need to declare a constant for acceleration (0.1 or 0.2 are good) and tally a vertical speed. You can then fall when the vertical speed gets to a certain value. Here's a small snippet, though if you have gravity you may want to edit it. First of all set vSpeed to say -8 by default.
public void jump() {
vSpeed += ACCELERATION;
if(vSpeed < 8)
dy += vSpeed;
else
vSpeed = -8;
falling = false;
}
I just wrote this off the top of my head, but basically, since moving upwards is taking away a number, you appear to jump when it adds negative numbers, then you'll start falling when it reaches 0, and land when reaches 8 again.
The problem is the way the OS handles key events and passes them to your application. When you press a key, it fires an event for down. Then based on your settings for repeating, it will start pressing the key again after some amount of time, at some amount of frequency. (you can see this when typing. Press a key, and hold it).
When you press another key, it stops the repeated triggers for the other key. You can see this while typing as well. Hold a key, then start holding another. The original key stops, as you would expect.
This won't even be consistent with every os, and people could cheat in your game as it is, by making the repeat timer on their keyboard faster.
For these reasons, it's a very bad idea to do animations inside of key listeners. You should be settings flags to true/false and reading them in a game loop. (As demonstrated in #Troubleshoot's answer).
I am working with disabled children, who have cerebral palsy. One child has limited fine motor control, so she currently uses a joystick to control the mouse, and it's traverse rate is set very low. This works well for her, as she can click all buttons on the screen, but I think we could do better - when she wants to traverse the whole screen it takes an age to do so (about 10 seconds).
My hypothesis is that her brain is fine, and only her motor control is poor. If that's true, I believe that a mouse that started at a low speed, but experienced a constant acceleration, would be better for her, as it would pick up speed and become quick when traversing the whole screen.
If this works, then we could be tweaking PID control, and velocity/acceleration setting for a great number of disabled people, speeding up their access and hence their learning and development.
But I do not know the best way to build this - all suggestions, thoughts, links and tips welcome.
To begin with I have tried using Processing and Java, and using a mouseListener, and a Robot to control the cursor. I'm not convinced that this is the best way though, as I'm reading the cursor position and then writing to it, so my best attempts still make the cursor jump around, and there is not smooth movement. Is it achievable in Java? Do I need to read the mouse input from the USB using some kind of driver, and then replace the plotting of the cursor on screen with my own?
I've made a couple of videos to illustrate the effect I am trying to bring about.
The Status quo (my illustration is driving the cursor off the arrow keys)
http://www.youtube.com/watch?v=3ZhQCg5DJt8
The new behaviour I want (mouse accelerates)
http://www.youtube.com/watch?v=JcBK_ZCFGPs
if it's any use, the Processing code I used to make those demos is copied in below:
Status quo demo:
import java.awt.AWTException;
import jav
a.awt.Robot;
Robot robot;
int i = 0;
int j = 0;
void setup() {
setupDotgame();
try {
robot = new Robot();
}
catch (AWTException e) {
e.printStackTrace();
}
robot.mouseMove(screenWidth/2, screenHeight/2);
}
void draw() {
//println(frameCount);
robot.mouseMove(screenWidth/2+8*i, screenHeight/2+8*j);
drawDotgame();
}
void keyPressed() {
if (keyCode == UP) {
j--;
}
else if (keyCode == DOWN) {
j++;
}
else if (keyCode == RIGHT) {
i++;
}
else if (keyCode == LEFT) {
i--;
}
}
Desired behaviour:
import java.awt.AWTException;
import java.awt.Robot;
Robot robot;
int i = 0;
int j = 0;
int delta = 8;
int time = 0;
void setup() {
setupDotgame();
try {
robot = new Robot();
}
catch (AWTException e) {
e.printStackTrace();
}
robot.mouseMove(screenWidth/2, screenHeight/2);
}
void draw() {
//println(frameCount);
robot.mouseMove(screenWidth/2+i, screenHeight/2+j);
drawDotgame();
}
void keyPressed() {
if (millis() - time < 90) {
delta += 8;
}
else { delta = 8; }
time = millis();
if (keyCode == UP) {
j-=delta;
}
else if (keyCode == DOWN) {
j+=delta;
}
else if (keyCode == RIGHT) {
i+=delta;
}
else if (keyCode == LEFT) {
i-=delta;
}
}
And the DotGame code they both reference:
void setupDotgame() {
size(1000, 600);
background(255);
fill(255, 0, 0);
noStroke();
smooth();
drawCircle();
}
void drawDotgame() {
if (get(mouseX, mouseY) != color(255)) {
background(255);
drawCircle();
}
}
void drawCircle() {
int x = round(random(50, width-50));
int y = round(random(50, height-50));
int rad = round(random(20, 80));
ellipse(x, y, rad, rad);
}
Thanks in advance
as Carl suggested, I believe the best answer short of making the mouse actually have this behavior, is some sort of jumping behavior that will get the mouse fairly close to where you need to go, then use the joystick from there.
I happen to know that a program called AutoItv3 can do this sort of thing. You could set it up to recognize special hotkeys, then have that hotkey move the mouse to whatever region you wish.
Commands useful for this are HotKeySet, MouseMove, and Func/EndFunc.
In CS class we made a simple game using a program called greenfoot. This game was much like the game "Frogger" if you are familiar. I am now practicing on my own, and want to make a game similar. My new game is going to be somewhat close to PacMan. The game I made before I control a rocket ship that needs to reach the top of the screen. Meanwhile, I have made randomly selected sizes and speeds for rectangles bouncing of the walls. But, I want to make it more interesting for my new game. I want a loop for these objects that create a random direction when it is first complies, and bounce of the walls and continue on in that direction, much like that famous screen saver that bounces around. Here is my code for the first game, is it anything like this? So ultimately my question is, how do I write a loop for a random direction.
public boolean canMoveRight()
{
if ( getX() + 1 < getWorld().getWidth() )
return true;
else
return false;
}
public boolean canMoveLeft()
{
if ( getX() - 1 > 0 )
return true;
else
return false;
}
public void moveRight()
{
setLocation( getX() + speed, getY() );
}
public void moveLeft()
{
setLocation ( getX() - speed, getY() );
}
public void act()
{
if (right==true)
{
if (canMoveRight() )
{
moveRight();
}
else
{
right = false;
}
}
else
{
if( canMoveLeft() )
moveLeft();
else
right = true;
}
}
Define a Direction enum
e.g.
Up, RightUp,Right... LeftUp.
Use random to pick one.
Direction translates to a change in position of dX,dX, so with a movement step of say 1 pixel UpLeft is -1,-1 (origin top left !)
then in your loop simply add dx to X and dy to Y.
Something along these lines, I guess, would work:
Random random = new Random();
int direction = random.nextInt(1); // gives 0 or 1 randomly
if (direction == 0) {
// move left
} else {
// move right
}
Are you looking for something likes this?
int horz = ((Math.random() * 10) % 10) + 1; //I just choose 10 at random
int vert = ((Math.random() *10) % 10) + 1;
//You can use another random number to choose to negate either horz or vert if you want
//You can also use random numbers to define the start location.
public boolean canMoveHorz()
{
if ( (getX() + horz < getWorld().getWidth() && horz > 0) || (getX() + horz > 0 && horz < 0))
return true;
else
return false;
}
public boolean canMoveVert()
{
if ( (getY() + vert > 0 && vert < 0) || (getY() + vert < getWorld().getHeight() && vert > 0))
return true;
else
return false;
}
public void act() {
if(!canMoveHorz()) {
horz *= -1;
}
if(!canMoveVert()) {
vert *= -1;
}
setLocation(getX() + horz, getY() + vert);
}
This will require some tweaking but what it does is choose 2 random numbers that dictate the speed (vertically and horizontally) for the object. Then it moves the object in those directions until it reaches the edge of the World at which point it negates the speed so the object will move the opposite direction. This is not the same as a true bounce off the walls because I don't do anything with the angle of the hit to determine the angle of the bounce but this should be able to get you started. If you want a more realistic bounce you'll have to do some geometric calculations.