![]() ![]() |
Nov 18 2009, 10:06 AM
Post
#1
|
|
|
Active ![]() ![]() Group: Admin Posts: 115 Joined: 08-25-09 Member No.: 12610 |
The next project we will be working on is Space Invaders. You will need to add several classes to your program to make it function properly.
1. A ship class: This will keep track of the player’s ship on screen. Very similar to our paddle class from Pong, the only difference is that instead of a rectangle, you may want to modify your class to draw an image of a ship on screen. To do that, you will have to add an image variable to your ship class (in addition to your standard x,y and speed variables). You should load the image of your ship in the constructor of your ship class (Remember: Your constructor initializes your ship, and constructor functions are always named public void SameNameAsTheClass(optional variables in here)). 2. An enemy class: Your enemies should keep track of their own x and y position on screen, as well as whether they are visible or not. You may also want to add speed variables to your enemy class, so that if you wanted each enemy to move at a different speed, you could set it up to do so. Your enemy class should also include a move function that moves your enemy around the screen, and a paint function that paints your enemy on the screen. 3. A bullet class: Your bullet class will represent the laser or bullets that your ship fires at the enemies coming in at it. Your bullet class should keep track of its x and y positions, as well as whether it is visible or not. It should also have a move function to move itself, and a paint function to paint itself. (I would suggest you make your bullets thin filled rectangles of whatever color you want to make it look like a laser). 4. A thread/timer class: Just like our other programs, we are going to need a thread to move all the stuff around our screen. As I discussed in class, if you don’t know how to start a class from scratch, you can copy and paste similar classes we have used in other projects into your game and modify them (the pong paddle class or the car class from frogger are good starting points for classes 1,2 and 3). Also, you will have 1 ship in your game and 1 timer, eventually you will have arrays of both bullets and enemies. Bullets: Once again, as we discussed in class, the procedure for firing a bullet is as follows: when the user presses whichever key you want to be your ‘fire’ key: loop through your bullet array and find the first bullet that is NOT visible (don’t forget you can break out of a loop with the “break” command), place it at the same x and y position as the one your ship is at (so it looks like its coming from the ship). Finally, in your timer class, you should loop through the bullets and move any bullet that IS visible (we don’t want to move invisible bullets) up. |
|
|
|
Nov 20 2009, 10:26 AM
Post
#2
|
|
|
Active ![]() ![]() Group: Admin Posts: 115 Joined: 08-25-09 Member No.: 12610 |
Here is basic code to help you get started.
import java.awt.*; import java.applet.*; import java.awt.event.*; public class SpaceInvaders extends Applet implements KeyListener{ Timer mt = new Timer(); Enemy badguys[] = new Enemy[15]; Ship s1 = new Ship(100,300); Bullet bulletz[] = new Bullet[5]; public void init() { addKeyListener(this); //initialize each row of my enemy ships for (int i=0; i<5;i++) { badguys[i] = new Enemy(i*11,10); } for (int i=5; i<10;i++) { badguys[i] = new Enemy((i-5)*11,30); } for (int i=10; i<15;i++) { badguys[i] = new Enemy((i-10)*11,50); } for (int i=0; i<5;i++) { bulletz[i]= new Bullet(-10,-10); } //start the move timer mt.start(); } public void keyPressed(KeyEvent e) { if (e.getKeyCode()==e.VK_LEFT) { s1.x=s1.x-10; } if (e.getKeyCode()==e.VK_RIGHT) { s1.x=s1.x+10; } if (e.getKeyCode()== e.VK_SPACE) { //fire a bullet //find the first bullet that isn't visible, and make it visible //note: our move timer moves all bullets that are VISIBLE //so we just have to set visible to true //for a higher mark, you will change this loop to a more efficient //WHILE loop instead of the for loop for (int i=0; i<5; i++) { if (bulletz[i].visible == false) { bulletz[i].x = s1.x; bulletz[i].y=s1.y; bulletz[i].visible = true; repaint(); break; //once we have found a bullet //that we can use we can stop searching } } } repaint(); } public void keyTyped(KeyEvent e) { } public void keyReleased(KeyEvent e) { } public void paint(Graphics g) { //paint all bad guys and bullets //note: if you look inside the paint functions inside the //enemy and bullet classes, you will see that they only paint //on screen if the bullet is VISIBLE for (int i = 0; i<15; i++) { badguys[i].paint(g); } for (int i=0; i<5; i++) { bulletz[i].paint(g); } s1.paint(g); } class Timer extends Thread { public void run() { while(true) { //move the bad guys and the bullets //note: if you look inside the moveDown and //moveUp functions inside the Enemy and Bullet //classes respectively, you will see that only VISIBLE //bullets and enemies are moved for (int i =0;i<15; i++) { badguys[i].moveDown(); } for (int i=0;i<5;i++) { bulletz[i].moveUp(); } //collision will go here //you will need a loop inside of a loop to do proper collision //because you will need to loop through each bullet and check //to see if it collided against each enemy //remember, we don't want invisible enemies and bullets colliding repaint(); try { sleep(500); } catch (Exception e) { System.out.println("thread error"); } } } }//end of timer class class Enemy { int x; int y; boolean visible = true; public Enemy(int x, int y) { //Enemy Constructor - init for your enemy class System.out.println("making an enemy"); this.x = x; this.y = y; } public void moveDown() { y= y + 10; } public void paint(Graphics g) { if (visible =true) { g.fillOval(x,y,10,10); } } }//end of enemy class class Ship { int x; int y; public Ship(int x, int y) { //Ship Constructor - init for your ship class System.out.println("making ship"); this.x = x; this.y = y; } public void paint(Graphics g) { g.fillRect(x,y,40,40); } }//end of ship class class Bullet { int x; int y; boolean visible = false; public Bullet(int x, int y) { //Bullet Constructor - init for your bullet class System.out.println("making a bullet"); this.x = x; this.y = y; } public void moveUp() { if (visible == true) { y= y - 10; } if (y<0) { visible = false; } } public void paint(Graphics g) { if (visible ==true) { g.fillRect(x,y,5,40); } } }//end of bullet class } |
|
|
|
Nov 20 2009, 10:27 AM
Post
#3
|
|
|
Active ![]() ![]() Group: Admin Posts: 115 Joined: 08-25-09 Member No.: 12610 |
Collision for Space Invaders:
To check collision, you need to check if EACH bullet has hit EACH enemy ship. To accomplish this, you will need a loop inside of a loop, as follows: for (int i=0;i<NUMBEROFBULLETS;i++) //loop through each bullet { for (int j=0;j<NUMBEROFENEMIES;j++) //loop through each enemy ship { //collision code will go here //remember, you are checking bulletz[i] and shipz[j] //if you mix up i and j, your game will compile but it //will have unexpected results } } For the actual collision code, take a look at your collision code for Pong or Breakout, with the variables representing the ball being replaced by the variables for your bullets, and the variables representing your paddles or bricks being replaced by variables for your enemy ships. |
|
|
|
Nov 20 2009, 10:27 AM
Post
#4
|
|
|
Active ![]() ![]() Group: Admin Posts: 115 Joined: 08-25-09 Member No.: 12610 |
Here is some of the code we discussed in class to make your alien ships fire bullets (remember, you can either make a new array of bullets, or if you want the alien bullets to look differently from the player's bullets you would make a new class)
Note: As always a class is just a blue-print of an object you want to create, to make an object that you can actually use you will have to declare it at the top of your code with your variables (and start it in this case because it is a thread). Either way, you will have to do the same steps you needed to create your regular bullets to create your alien bullets: 1. Declare your array at the top 2. initialize the array inside your init (I put the alien bullets off-screen at -50,-50 at first because they should all be INVISIBLE when you start the program 3. Add code to your paint to have the alien bullets that ARE visible paint on screen 4. Add code to your regular move Timer to move alien bullets that ARE visible Finally, you will have to add collision code between your alien bullets and your player's ship, and make something happen when the bullets hit the ship (lose a life, lose health, lose shield, etc). class ShootTimer extends Thread { public void run() { while(true) { System.out.println("Shoot!"); //pick a random number of bullets to fire //remember, my code had an array of 5 alien bullets so I had //to pick a random number between 0 and 4 //you may decide on more or less bullets for your game int numBullets = (int)(Math.random()*4.0); //we will use the whichAlien variable to pick a different //alien ship to fire from each time int whichAlien; for (int i=0; i<numBullets; i++) { //loop from 0 to the number of bullets you chose //to fire this time, and only fire alien bullets //that are not currently in use if (alienBullets[i].visible == false) { //need to pick a random alien ship to fire from //make sure the alien ship is visible //don't want invisible ships firing if (badguys[whichAlien].visible == true) { //put the alien bullet on screen at the //same x and y position of the alien ship //that was picked, then make the bullet //visible } } } repaint(); try { //can either sleep for a constant amount, or pick a //random number so your game is less repetitive sleep( ); } catch (Exception e) { System.out.println("thread error"); } } } }//end of timer class As we discussed in class, there are still problems with using a for loop to loop through and find the available bullets and fire them because it is always looking at the first three bullets. The best way to accomplish this would be to use a while loop to replace the for loop. int howmanylookedat = 0; //boolean that tells us if we are done looking int count = 0; //how many bullets have we looked at while ((howmanylookedat!=numBullets)||(count!=5)) //while we aren't done getting bullets, OR we haven't run out of //bullets to look at keep looping { //our code to actually pick a bullet and put it by a ship would go in here //remember to increment (add 1) to howmanylookedat and count, or you may end up //with an infinite loop } |
|
|
|
Nov 20 2009, 10:28 AM
Post
#5
|
|
|
Active ![]() ![]() Group: Admin Posts: 115 Joined: 08-25-09 Member No.: 12610 |
Space Invaders for marking scheme:
The following is affects your mark on every project Efficient Algorithms -An efficient algorithm executes rapidly, requires minimal storage and is simple to look at. Program execution - Programs runs as described and expected, without generating syntax or logic errors. Programming Style - The code is easily readable with indentation, proper use of structures, functions, and meaningful variable names. Functionality – Does the program meet the basic functionality of the project? Additional/improved functionality will raise your mark. Your game should do the following: For a C: The game works similar to the example I have provided. - You have used images instead of circles and squares in the game. - You have a score - The game ends (either if you win or you lose) For a B: The game has improved on the examples I have provided. - all of the above - there is a score on screen - the player has x amount of lives - the game ends BOTH if the player wins or loses For an A: The game has significantly improved on my example. - all of the above - multiple difficulty levels - any other ideas that improve gameplay (e.g. a boss enemy once all the regular enemies are defeated, shields, power-ups: shields, extra life, improved firepower, etc.) |
|
|
|
Dec 8 2009, 10:08 AM
Post
#6
|
|
|
Active ![]() ![]() Group: Admin Posts: 115 Joined: 08-25-09 Member No.: 12610 |
for (int i=0; i<5; i++) //loop through each bullet
{ for (int j=0; j<15; j++) //loop through each ship { if ((bulletz[i].y+bulletz[i].height)>=badguys[j].y) { //only checked if condition 1 is true if ((bulletz[i].y)<=(badguys[j].y+badguys[j].height)) { //only checked if condtion 1 and 2 are true if (bulletz[i].x<=(badguys[j].x+badguys[j].width)) { //only checked if the first 3 conditions are true if ((bulletz[i].x + bulletz[i].width)>=badguys[j].x) { if ((bulletz[i].visible==true)&&(badguys[j].visible == true)) { //if our program has gotten to here, that means //all 4 conditions must be true System.out.println("I think we hit an enemy ship" + j + " with bullet " + i); bulletz[i].visible = false; badguys[j].visible = false; } } } } } } } |
|
|
|
![]() ![]() |
| Lo-Fi Version | Time is now: 9th February 2010 - 02:36 AM |