We are about to switch to a new forum software. Until then we have removed the registration on this forum.
Hi there, i was recommended this forum by my college. I have created a racing game where you control one of the space ships and have to race 3 other computer controlled ships around a track.
Everything works how i want however I am having issues keeping my ship on the track. The collision detection i have used only works for LEFT and RIGHT controls but for UP and DOWN the ship will go off the track. Any advice or pointers on where i have gone wrong would really help! Thanks.
The exact code in reference to the movement is here:
if (posX < 200 && posX< 1050 && posY > 150 && posY< 650){ //TRIED A VARIATION ON COLLISION CONTROL BUT IT DIDN'T WORK. LEFT IT IN FOR THE CODE TO BE SEEN.
boolean is_ship_on_the_track = true;
}
if (is_the_LEFT_key_down) { //WHAT TO DO IF CERTAIN KEYS ARE PRESSED
if ((red(get(int(posX-10),int(posY)))==255))
{
posX-=0;
}
else
{
posX-=5;
}
}
if (is_the_RIGHT_key_down) {
if ((red(get(int(posX+15),int(posY)))==255))
{
posX-= 0;
}
else
{
posX += 5;
}
}
if (is_the_UP_key_down) {
if ((red(get(int(posX),int(posY-10)))==255)) // PLAYING AROUND WITH OPTIONS TO GET THE SHIP TO STAY ON THE TRACK
{
posY-= 0;
}
else
{
posY-=5;
}
}
if (is_the_DOWN_key_down) {
if ((red(get(int(posX),int(posY+15)))==255)) // PLAYING AROUND WITH OPTIONS TO GET THE SHIP TO STAY ON THE TRACK
{
posY-= 0;
}
else
{
posY+=5;
}
}
The entire code is below. I have pasted the images at the bottom. Thank you!
BOUNDARY TAB:
void boundary() { //SETTING THE FUNCTION FOR THE TRACKS BOUNDARY TO APPEAR IN ORANGE
stroke(255);
strokeWeight(160);
bezier(200, 450, 200, 100, 900, 100, 900, 175);
bezier( 900, 175, 900, 450, 900, 450, 1050, 450);
bezier( 1050, 450, 1200, 450, 1400, 600, 900, 600);
bezier( 900, 600, 600, 600, 400, 600, 200, 450);
}
STARTLINE TAB:
void startLine () { //SETTING THE FUNCTION FOR THE START/FINISH LINE
noStroke();
fill (random(0, 255), random(0, 127), random(0, 80), 255);
quad(270, 420, 135, 460, 153, 500, 295, 436);
}
TRACK TAB:
void track() { //SETTING THE FUNCTION FOR THE TRACK
fill(255, 0);
stroke(#555555);
strokeWeight(140);
beginShape();
vertex(200, 450);
bezierVertex( 200, 100, 900, 100, 900, 175);
bezierVertex( 900, 450, 900, 450, 1050, 450);
bezierVertex( 1200, 450, 1400, 600, 900, 600);
bezierVertex( 600, 600, 400, 600, 200, 450);
endShape();
}
WORDS TAB:
void words() { //SETTING THE FUNCTION FOR THE TEXT THAT WILL APPEAR ON THE GAME
textSize(40);
fill(0);
text("Alien Race v2.0", 20, 50);
textSize(30);
text("Use Arrow Keys To", 1035, 100);
text("Control Your Ship", 1040, 130);
text("First Across the Line Wins!", 1000, 170);
textSize(25);
text("Press UP Arrow Key To Begin", 1020, 200);
}
MAIN CODE:
//TO START THE GAME YOU NEED TO PRESS THE UP ARROW KEY
//THEN YOU CONTROL YOUR SHIP USING THE ARROW KEYS
import ddf.minim.*; //LOADING THE MUSIC LIBRARY
Minim minim=new Minim(this);
AudioPlayer player2; //THE DIFERENT AUDIO PLAYERS REQUIRED
AudioPlayer player3;
AudioPlayer player4;
PImage img; //LOADING THE IMAGES
PImage img2;
PImage img3;
PImage img4;
PImage img5;
PImage img11;
PImage img33;
float posX = 200; //SETTING THE START X-COORDINATE FOR THE PLAYERS SHIP
float posY = 390; //SETTING THE START Y-COORDINATE FOR THE PLAYERS SHIP
int state; //SETTING THE STATE FOR THE GAME
boolean is_the_UP_key_down = false; //SETTING THE VARIABLES TO TRACK WHETHER THE KEYS USED IN THE GAME ARE PRESSED OR NOT
boolean is_the_DOWN_key_down = false;
boolean is_the_LEFT_key_down = false;
boolean is_the_RIGHT_key_down = false;
boolean is_ship_on_the_track = true;
void setup() {
noLoop(); //STARTING THE GAME WITH NO LOOP SO THE ALIEN SHIPS DON'T AUTOMATICALLY START GOING ROUND THE TRACK
size(1400, 700);
smooth(8);
state =0; //HERE I AM STATING THE CURRENT GAME STATE
frameRate(25);
imageMode (CENTER); //BY SETTING THE IMAGE MODE TO CENTER IT ENABLES ME TO TRACK THE X,Y POSITIONS OF THE IMAGES FOR WHEN THEY CROSS THE FINISHING LINE
player2 =minim.loadFile("cheer.mp3"); //LOADING THE SPECIFIC SOUNDS
player3 =minim.loadFile("boo.mp3");
player4 =minim.loadFile("planet.mp3");
player4.play(); //I WANT THIS SOUND TO PLAY FROM THE MOMENT THE GAME IS STARTED SO I PUT IT IN SETUP RATHER THAN DRAW
player4.loop(); //THE SOUND FILE IS SHORTER THAT THE TIME IT WILL TAKE TO PLAY THE GAME SO I NEED IT TO LOOP
img = loadImage("0.png"); //LOADING THE SPECIFIC IMAGE FILES FOR THE DIFERENT CHARACTERS
img2 = loadImage("alien1.png");
img3 = loadImage("alien2.png");
img4 = loadImage("alien3.png");
img5 = loadImage("alien4.png");
img33 = loadImage("planet.jpg"); //THE BACKGROUND IMAGE
}
float f = 0.0175; //SETTING THE VARIABLES FOR THE COMPUTER CONTROLLED SHIPS, SPECIFICALLY THEIR MOMENTUM WHEN THEY GO ROUND THE CIRCUIT
float t = 0.01;
float h = 0.0075;
float j = 0.0125;
void draw() {
println(get(mouseX, mouseY));
if (state==0) //STATE 0 IS WHEN THE GAME BEGINS SO I HAVE TO CALL UP MY FUNCTIONS AND SET CERTAIN VARIABLES
{
f += 0.009; //THE ADDITIONAL MOMENTUM I WANT THE COMPUTER CONTROLLED SHIPS TO GET THROUGH THE GAIM
t += 0.0065;
h += 0.0045;
j += 0.0075;
background(img33);
boundary(); //CALLING UP MY FUNCTIONS
track();
startLine();
words();
image(img, posX, posY); //SETTING THE START POSITION AND CALLING UP THE IMAGE FOR THE PLAYERS CONTROLLED SHIP
if (posX < 200 && posX< 1050 && posY > 150 && posY< 650){ //TRIED A VARIATION ON COLLISION CONTROL BUT IT DIDN'T WORK. LEFT IT IN FOR THE CODE TO BE SEEN.
boolean is_ship_on_the_track = true;
}
if (is_the_LEFT_key_down) { //WHAT TO DO IF CERTAIN KEYS ARE PRESSED
if ((red(get(int(posX-10),int(posY)))==255))
{
posX-=0;
}
else
{
posX-=5;
}
}
if (is_the_RIGHT_key_down) {
if ((red(get(int(posX+15),int(posY)))==255))
{
posX-= 0;
}
else
{
posX += 5;
}
}
if (is_the_UP_key_down) {
if ((red(get(int(posX),int(posY-10)))==255)) // PLAYING AROUND WITH OPTIONS TO GET THE SHIP TO STAY ON THE TRACK
{
posY-= 0;
}
else
{
posY-=5;
}
}
if (is_the_DOWN_key_down) {
if ((red(get(int(posX),int(posY+15)))==255)) // PLAYING AROUND WITH OPTIONS TO GET THE SHIP TO STAY ON THE TRACK
{
posY-= 0;
}
else
{
posY+=5;
}
}
fill(0, 0, 0, 0); //THIS IS THE PATH I WANT COMPUTER CONTROLLED SHIP 1 TO FOLLOW AROUND THE TRACK
if (f < 1) {
float x = bezierPoint( 230, 230, 930, 930, f);
float y = bezierPoint( 450, 100, 100, 175, f);
image(img2, x, y);
}
else if ( f < 2 ) {
float x = bezierPoint( 930, 930, 930, 1020, f-1); // THE IF STATEMENTS ENSURE THAT THE SHIPS DON'T GO TO FAST OR CUT CORNERS
float y = bezierPoint( 175, 450, 450, 450, f-1);
image(img2, x, y);
}
else if ( f < 3 ) {
float x = bezierPoint( 1020, 1170, 1350, 880, f-2);
float y = bezierPoint( 450, 450, 600, 600, f-2);
image(img2, x, y);
}
else if ( f < 4 ) {
float x = bezierPoint( 880, 630, 430, 230, f-3);
float y = bezierPoint( 600, 600, 600, 450, f-3);
if (x > 135 && x < 270 && y > 420 && y<460) //THIS IF STATEMENT IS FOR WHAT STATE THE GAME SHOULD GO TO WHEN THE SHIP CROSSES THE FINISHING LINE
{
state=4;
}
image(img2, x, y);
}
else if ( f > 4 ) {
f = 0;
}
if (h < 1) { //THIS IS THE PATH I WANT COMPUTER CONTROLLED SHIP 2 TO FOLLOW AROUND THE TRACK
float x = bezierPoint( 200, 200, 900, 900, h);
float y = bezierPoint( 460, 110, 110, 185, h);
image(img3, x, y);
}
else if ( h < 2 ) {
float x = bezierPoint( 900, 900, 900, 1050, h-1);
float y = bezierPoint( 185, 460, 460, 460, h-1);
image(img3, x, y);
}
else if ( h < 3 ) {
float x = bezierPoint( 1050, 1200, 1400, 900, h-2);
float y = bezierPoint( 460, 460, 610, 610, h-2);
image(img3, x, y);
}
else if ( h < 4 ) {
float x = bezierPoint( 900, 600, 400, 200, h-3);
float y = bezierPoint( 610, 610, 610, 460, h-3);
if (x > 135 && x < 270 && y > 420 && y<460) //THIS IF STATEMENT IS FOR WHAT STATE THE GAME SHOULD GO TO WHEN THE SHIP CROSSES THE FINISHING LINE
{
state=3;
}
image(img3, x, y);
if (x > 135 && x < 270 && y > 420 && y<460)
{
state=3;
}
}
else if ( h > 4 ) {
h = 0;
}
if (t < 1) { //THIS IS THE PATH I WANT COMPUTER CONTROLLED SHIP 3 TO FOLLOW AROUND THE TRACK
float x = bezierPoint( 200, 200, 900, 900, t);
float y = bezierPoint( 450, 100, 100, 175, t);
image(img4, x, y);
}
else if ( t < 2 ) {
float x = bezierPoint( 900, 900, 900, 1050, t-1);
float y = bezierPoint( 175, 450, 450, 450, t-1);
image(img4, x, y);
}
else if ( t < 3 ) {
float x = bezierPoint( 1050, 1200, 1400, 900, t-2);
float y = bezierPoint( 450, 450, 600, 600, t-2);
image(img4, x, y);
}
else if ( t < 4 ) {
float x = bezierPoint( 900, 600, 400, 200, t-3);
float y = bezierPoint( 600, 600, 600, 450, t-3);
if (x > 135 && x < 270 && y > 420 && y<460) //THIS IF STATEMENT IS FOR WHAT STATE THE GAME SHOULD GO TO WHEN THE SHIP CROSSES THE FINISHING LINE
{
state=2;
}
image(img4, x, y);
}
else if ( t > 4 ) {
t = 0;
}
if (posX > 135 && posX < 270 && posY > 420 && posY<460)
{
state=1; //THIS IF STATEMENT IS FOR WHAT STATE THE GAME SHOULD GO TO WHEN THE SHIP CROSSES THE FINISHING LINE
}
if (j < 1) { //THIS IS THE PATH I WANT COMPUTER CONTROLLED SHIP 4 TO FOLLOW AROUND THE TRACK
float x = bezierPoint( 205, 205, 905, 905, j);
float y = bezierPoint( 460, 110, 110, 185, j);
image(img5, x, y);
}
else if ( j < 2 ) {
float x = bezierPoint( 905, 905, 905, 1055, j-1);
float y = bezierPoint( 185, 460, 460, 460, j-1);
image(img5, x, y);
}
else if ( j < 3 ) {
float x = bezierPoint( 1055, 1205, 1405, 905, j-2);
float y = bezierPoint( 460, 460, 610, 610, j-2);
image(img5, x, y);
}
else if ( j < 4 ) {
float x = bezierPoint( 905, 605, 405, 205, j-3);
float y = bezierPoint( 610, 610, 610, 460, j-3);
if (x > 135 && x < 270 && y > 420 && y<465) //THIS IF STATEMENT IS FOR WHAT STATE THE GAME SHOULD GO TO WHEN THE SHIP CROSSES THE FINISHING LINE
{
state=2;
}
image(img5, x, y);
}
else if ( j > 4 ) {
j = 0;
}
if (posX > 135 && posX < 270 && posY > 420 && posY<460)
{
state=1; //THIS IF STATEMENT IS FOR WHAT STATE THE GAME SHOULD GO TO WHEN THE SHIP CROSSES THE FINISHING LINE
}
if (state==1) //WHAT TEXT AND SOUNDS THERE SHOULD BE DEPENDING ON WHICH SHIP CROSSES THE FINISHING LINE
{
player4.pause();
player2.play();
fill (255, 0, 0);
textSize (100);
text ("You Win", 375, 400);
}
if (state==2)
{
player4.pause();
player3.play();
fill (0, 0, 255);
textSize (60);
text ("Alien 3 Wins", 350, 400);
}
if (state==3)
{
player4.pause();
player3.play();
fill (0, 0, 255);
textSize (60);
text ("Alien 2 Wins", 350, 400);
}
if (state==4)
{
player4.pause();
player3.play();
fill (255, 255, 255);
textSize (60);
text ("Alien 1 Wins", 350, 400);
}
}
}
void keyPressed() { //SETTING THE VARIABLES FOR THE KEY PRESSED TO TRUE IF THE PLAYER PRESSES THAT KEY OR HOLDS IT DOWN
if (keyCode == UP) {
is_the_UP_key_down=true;
loop(); //WHEN THE KEY UP IS FIRST PRESSED I WANT THE GAME TO START
}
if (keyCode == DOWN) {
is_the_DOWN_key_down=true;
}
if (keyCode == LEFT) {
is_the_LEFT_key_down=true;
}
if (keyCode == RIGHT) {
is_the_RIGHT_key_down=true;
}
}
void keyReleased() { //SETTING THE VARIABLE TO FALSE FOR WHEN THE PLAYER ISN'T PRESSING A KEY TO STOP THE SHIP AUTOMATICALLY MOVING
if (keyCode == UP) {
is_the_UP_key_down=false;
}
if (keyCode == DOWN) {
is_the_DOWN_key_down=false;
}
if (keyCode == LEFT) {
is_the_LEFT_key_down=false;
}
if (keyCode == RIGHT) {
is_the_RIGHT_key_down=false;
}
}
Answers
You'd be much better off posting your code in the form of an SSCCE. Post a basic example using rectangles instead of images, and eliminate all of the extra code you have not directly related to your question.
That being said, let me ask a dumb question: you say horizontal collision detection is working. Why not just use that same logic, just switched for the vertical axis?
I will try now to make a mini version of my code so the issue is more visible.
I did use exactly the same logic for the vertical axis but it still doesn't work.
For left the code is:
if ((red(get(int(posX-15),int(posY)))==255))
For right the code is:
if ((red(get(int(posX+15),int(posY)))==255))
For Up the code is:
if ((red(get(int(posX),int(posY-15)))==255))
For Down the code is:
if ((red(get(int(posX),int(posY+15)))==255))
I have now edited my code down to the basics. It still uses 1 image which i have pasted below, but this code all works as intended and highlights my issue.
http://forum.processing.org/two/uploads/imageupload/704/1LQOW0PANVI6.png
That's an interesting way of checking where the space ships are! Why don't you just check the positions itself? As in,
if(posY < 0) posY = 0;
?Hint: when you do ctrl+T in Processing, it auto-formats the code for you which makes it a lot easier to read here.
I thought it would be best to check the position/collision based on colour because i have created a block coloured barier and the track that the ships go around is curved.
My biggest confusion is why my code works how i want it to, including the movements for Left & Right but does not work for Up & Down.
Next time i need to post any code i will ensure that i use that Hint, thank you.
If the track is curved, maybe that's not even that bad of an idea. Gotta keep that in mind.
I think I found the problem though. In Processing, Y = 0 at the top and
height
at the bottom. This means, if you go up, you need to check the colour of the pixel with a lower Y value (and vice versa for going down).if ((red(get(int(posX),int(posY+15)))==255))
needs to beif (red(get(int(posX),int(posY-15)))==255)
.Processing isn't very reliable for color-based checking! B/c it blends a pixel being rendered based on the color of the 1 present.
And all transparent colors are converted to their opaque counterpart as well!
Doing color checks on separate PGraphics layers has more chances of success though! B-)
Exactly like GoToLoop said, use an offscreen buffer (PGraphics) as collision Map.
Played around with your code. The following snippet is really basic, but should get you started: