The Challenge: |---->Program a 2d tank application in the language of your choice that adheres to the following:
#-The tank must rotate using the left and right directional keys.
#-The tank must loosely resemble a tank.
#-The tank must move forward or backward respectively from the direction it is facing using the up and down directional keys.
#-Pressing spacebar must fire a 'shot' in the direction the tank is facing.
#-The perspective of the user must be fixed and facing down at the tank.
#-The tank, shot, and ground must each have their own color. (all shots may have the same color)
/* Copyright (c) 2010 Xarn
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to
* deal in the Software without restriction, including without limitation the
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
* sell copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
Disclaimer: this code has many examples of "bad practices" because I was 100% focused on minimize coding time while meeting the requirements
import java.awt.*;
import java.applet.*;
import java.util.*;
import java.awt.event.*;
import java.awt.image.*;
public class a extends Applet implements Runnable,KeyListener{
double x,y;
double r,sdx,sdy;
boolean left,right,down,up;
double sx=-5,sy=-5;
int TANK_SIZE=20;
BufferedImage buf;
public void init(){
x=getWidth()/2;
y=getHeight()/2;
addKeyListener(this);
buf=new BufferedImage(getWidth(),getHeight(),BufferedImage.TYPE_3BYTE_BGR);
new Thread(this).start();
}
public void update(Graphics g){
paint(buf.getGraphics());
g.drawImage(buf, 0,0,null);
}
public void paint(Graphics g){
int[] xpoints=new int[8];
int[] ypoints=new int[8];
for(int i=0;i<4;i++){
xpoints[i]=(int)(x+TANK_SIZE*Math.cos(r+i*Math.PI/2));
ypoints[i]=(int)(y+TANK_SIZE*Math.sin(r+i*Math.PI/2));
}
xpoints[4]=(4*xpoints[0]+5*xpoints[3])/9;
ypoints[4]=(4*ypoints[0]+5*ypoints[3])/9;
xpoints[5]=(int)(x+1.5*TANK_SIZE*Math.cos(r-3*Math.PI/11));
ypoints[5]=(int)(y+1.5*TANK_SIZE*Math.sin(r-3*Math.PI/11));
xpoints[6]=(int)(x+1.5*TANK_SIZE*Math.cos(r-3*Math.PI/13));
ypoints[6]=(int)(y+1.5*TANK_SIZE*Math.sin(r-3*Math.PI/13));
xpoints[7]=(5*xpoints[0]+4*xpoints[3])/9;
ypoints[7]=(5*ypoints[0]+4*ypoints[3])/9;
g.setColor(Color.gray);
g.fillRect(0, 0, getWidth(), getHeight());
g.setColor(Color.green);
g.fillPolygon(xpoints,ypoints,8);
if(left)
r-=.1;
if(right)
r+=.1;
double dx=Math.cos(r-Math.PI/4);
double dy=Math.sin(r-Math.PI/4);
if(up){
x+=dx*10;
y+=dy*10;
}
if(down){
x-=dx*10;
y-=dy*10;
}
g.setColor(Color.yellow);
if(sx!=-5&&sy!=-5){
sx+=sdx;
sy+=sdy;
}
if(sx<-3||sx>getWidth()||sy<-3||sy>getWidth()){
sx=-5;
sy=-5;
}
g.fillOval((int)sx-1, (int)sy-1,3, 3);
}
public void run() {
while(true){
Graphics g=getGraphics();
if(g!=null)
update(getGraphics());
try{
Thread.sleep(30);
}catch(Exception e){}
}
}
public void keyPressed(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_UP:
up=true;
break;
case KeyEvent.VK_DOWN:
down=true;
break;
case KeyEvent.VK_LEFT:
left=true;
break;
case KeyEvent.VK_RIGHT:
right=true;
break;
case KeyEvent.VK_SPACE:
if(sx==-5&&sy==-5){
sx=x;
sy=y;
sdx=Math.cos(r-Math.PI/4)*20;
sdy=Math.sin(r-Math.PI/4)*20;
}
break;
}
}
public void keyReleased(KeyEvent e) {
switch(e.getKeyCode()){
case KeyEvent.VK_UP:
up=false;
break;
case KeyEvent.VK_DOWN:
down=false;
break;
case KeyEvent.VK_LEFT:
left=false;
break;
case KeyEvent.VK_RIGHT:
right=false;
break;
}
}
public void keyTyped(KeyEvent e){}
}
>>16 #ifndef M_PI #define M_PI 3.14159265358979323846 #endif
This is unnecessary if you define _BSD_SOURCE or _XOPEN_SOURCE=500. The math.h man page doesn't tell you this for some reason, but M_PI isn't part of ANSI C, so compiling with -ansi undefines it (along with a bunch of other constants).
I initially thought glibc was being retarded, but it turns out it was just poor documentation.
Name:
Anonymous2010-05-14 20:05
>>22
It wasn't written for shortness or readability thus the disclaimer, 100% code time. Also the ugliest part is the tank drawing which the C version sidesteps by using images.
compared to the boilerplate needed for win32, opengl or directx to do the same? yes, no contest
Name:
Anonymous2010-05-14 22:17
using System;
using System.Collections.Generic;
using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
static class Program
{
static void Main(string[] args)
{
using (TankGame game = new TankGame()) game.Run();
}
}
public class Entity
{
public Texture2D Texture;
public Vector2 Location;
public float Facing;
public float Velocity;
public Vector2 Origin { get { return new Vector2(this.Width / 2, this.Height / 2); } }
public int Height { get { return Texture.Height; } }
public int Width { get { return Texture.Width; } }
spriteBatch.Begin();
this.tank.Draw(this.spriteBatch);
foreach (Entity shot in shots) shot.Draw(this.spriteBatch);
spriteBatch.End();
base.Draw(gameTime);
}
}
Name:
Anonymous2010-05-14 22:28
>>25
I can only assume you've never used a game programming or graphic library yourself.
You can even leave out END_OF_MAIN(), if you like. It's only there for the retarded platforms. It saves you the effort of having to write a WinMain by hand.
>>30
So why not do the same WinMain hack in Allegro that SDL is using? All they do is #define main to SDLmain or something, and link the "real" main in the library itself.
>>33
How many is enough? Engineers and physicists usually claim to need about 3-5. I need about 7. Almost no one needs as much as 12, but since it's a constant: why not?
public void keyPressed(KeyEvent e) {
int key = e.getKeyCode();
//System.out.println("test ");
if ( key == KeyEvent.VK_UP )
up = true;
if ( key == KeyEvent.VK_LEFT )
left = true;
if ( key == KeyEvent.VK_DOWN )
down = true;
if ( key == KeyEvent.VK_RIGHT )
right = true;
repaint();
e.consume();
}
public void keyReleased(KeyEvent e) {
int key = e.getKeyCode();
int i;
if ( key == KeyEvent.VK_UP )
up = false;
if ( key == KeyEvent.VK_LEFT )
left = false;
if ( key == KeyEvent.VK_DOWN )
down = false;
if ( key == KeyEvent.VK_RIGHT )
right = false;
if ( key == KeyEvent.VK_SPACE)
{
for(i = 0; i < 3; i++)
{
if(shots[i].active == false)
{
shots[i] = new burret(xpos, ypos, counter);
shots[i].active = true;
i = 3;
}
}