What if you put extra efforts on video game assignments----7
A downloadable game for Windows
Dragster
Project Description
A recreation of classic Atari dragster game with better graphics.
Assignment Rubrics
- 1 point - have a title screen on which pressed a given key to starts the countdown timer
- 3 points - have a countdown timer of some sort (during which pressing the accelerator will result in a false start)
- 1 point - pressing a given key will start moving the player forward
- 1 point - the player accelerates the longer they hold down the key
- 1 point - a results screen appears after crossing the finish line or false starting
- 2 points - the total travel time (time from the end of the countdown to crossing the finish line)/if the player false started is shown on the results screen
- 1 point - a given key allows the game to restart when on the results screen
- Extra Credit (2 points) - implement a system of gear shifting or another method of changing the player's speed
- Extra Credit (1 point) - add particles
My Code
# Dragster Game, Phew
AIR_COEFF = 3
GEAR_SHIFT_CD = 30
gearFrameAfterFirstPress = 0
renderQueue = []
particles = []
MAIN_MENU = 0
COUNT_DOWN = 1
PLAYING = 2
RESULT = 3
gameState = MAIN_MENU
countdownTime = 3 # second
gameTimer = 0
startTime = 0
countdownStarted = False
gameOver = False
GOMsg = "Err"
def setup():
global car, renderQueue, fg, particles
size(800,600)
loadAssets()
car = Car(7000, 4, 90, 500000)
bg = CityBackground(T_BG1, T_BG2, 000, car, 100.0)
mg = CityBackground(T_MG1, T_MG2, 000, car, 60.0)
fg = CityBackground(T_FG1, T_FG2, 000, car, 30.0)
renderQueue.append(bg)
renderQueue.append(mg)
renderQueue.append(fg)
renderQueue.append(car)
#Particle Init
for i in range(42):
particles.append(Particle(random(800), random(600), car.spd / -100, 200))
print("init success")
def draw():
global renderQueue, car, gameState, countdownTime, startTime, gameTimer, gameOver, GOMsg, countdownStarted
if gameState == MAIN_MENU:
mainMenu()
elif gameState == COUNT_DOWN:
#Init all data
if countdownStarted:
carInit()
gameTimer = millis()
#print(millis())
countdownStarted = False
gameOver = False
startTime = gameTimer + 1000 * countdownTime
else:
for obj in renderQueue:
obj.update()
obj.render()
if car.gear > 0:
gameOver = True
#print(car.gear)
gameState = RESULT
GOMsg = "Early Fault Start!"
if millis() > gameTimer + countdownTime * 1000:
gameState = PLAYING
ShowCountdown()
ControllerUpdate()
displayUI()
elif gameState == PLAYING:
background(0)
ControllerUpdate()
for obj in renderQueue:
obj.update()
obj.render()
for p in particles:
p.update()
p.render()
if p.lifespan <= 0:
particles.remove(p)
particles.append(Particle(random(width + 400), random(height), car.spd / -100, 200))
displayUI()
#displayDebugInfo()
checkGameOver()
#print("displayed Debug info")
elif gameState == RESULT:
resultPage()
def ControllerUpdate():
global gearFrameAfterFirstPress
if keyPressed:
# Shift Gear Up
if key == ' ':
if gearFrameAfterFirstPress == 0:
car.gearSwitch = True
gearFrameAfterFirstPress += 1
else:
car.gearSwitch = False
gearFrameAfterFirstPress += 1
# Full Throttle
if key == 'a':
car.throttle = True
else:
if gearFrameAfterFirstPress < GEAR_SHIFT_CD and gearFrameAfterFirstPress != 0:
gearFrameAfterFirstPress += 1
car.gearSwitch = False
elif gearFrameAfterFirstPress >= GEAR_SHIFT_CD:
gearFrameAfterFirstPress = 0
car.gearSwitch = False
print("CD complete")
car.gearSwitch = False
car.throttle = False
def displayDebugInfo():
global car, fg
textSize(20)
fill(0)
textAlign(LEFT)
text("Speed: " + str(car.spd), 0, 30)
text("Acce: " + str(car.acce), 0, 60)
text("airRes:" + str(car.airRes), 0, 90)
text("Gear: " + str(car.gear), 0, 120)
text("Dist: " + str(car.curDist) + "/" + str(car.goalDist), 0, 150)
text("Rev: " + str(car.rev) + "/" + str(car.maxRev), 0, 180)
text("fgPosX:" + str(fg.imgAX) + "/" + str(fg.imgBX) + str(fg.imgAX - fg.imgBX), 0, 210)
text("GState:" + str(gameState), 0, 240)
def loadAssets():
global T_BG1, T_BG2, T_MG1, T_MG2, T_FG1, T_FG2, T_Car, T_Tire
T_BG1 = loadImage("BackGround.png")
T_BG2 = loadImage("BackGround.png")
T_MG1 = loadImage("MiddleGround.png")
T_MG2 = loadImage("MiddleGround.png")
T_FG1 = loadImage("ForeGround.png")
T_FG2 = loadImage("ForeGround.png")
T_Car = loadImage("car.png")
T_Tire = loadImage("tire.png")
def mainMenu():
background(0)
fill(255)
textSize(32)
textAlign(CENTER)
text("Press P to Play", width / 2, height / 2)
textAlign(LEFT)
textSize(20)
text("Press SpaceBar to shift gear up", width / 2 - 300, height / 2 + 100)
text("Press A to throttle Up", width / 2 - 300, height / 2 + 130)
def resultPage():
background(50)
fill(255)
textSize(32)
textAlign(CENTER)
text("Press R to Reset", width / 2, height / 2)
textSize(50)
text(GOMsg, width / 2, height / 2 - 100)
def ShowCountdown():
remainingTime = countdownTime - int((millis() - gameTimer) / 1000)
#print(startTime)
fill(0, 0, 0, 120)
rectMode(CORNER)
rect(0, 0, width, height)
fill(255)
textSize(200)
textAlign(CENTER)
text(str(remainingTime), width / 2, height / 2)
def carInit():
global car
car.selfInit()
def checkGameOver():
global gameOver, GOMsg, gameState
if car.rev > car.maxRev:
GOMsg = "You lose! Engine Exploded"
gameOver = True
elif car.curDist > car.goalDist:
tempSec = int(millis() - startTime) / 1000
tempMils = nf(int(millis() - startTime) % 1000, 3)
GOMsg = ("You win! Time: " + str(tempSec) + "." + str(tempMils) + "s")
gameOver = True
if gameOver:
gameState = 3
def displayUI():
global car
# Display Rev
revRatio = float(car.rev) / float(car.maxRev)
fill(0, 255, 0)
if revRatio > 0.8:
fill(255, 0, 0)
rect(20, height - 50, revRatio * 200, 30)
#print(revRatio)
# Display Gear
fill(255)
textSize(20)
text("Gear: " + str(car.gear), 250, height - 30)
# Display Current Time
if gameState == COUNT_DOWN:
text("Time: 0.000", 400, height - 30)
else:
tempSec = int(millis() - startTime) / 1000
tempMils = nf(int(millis() - startTime) % 1000, 3)
text("Time: " + str(tempSec) + "." + str(tempMils), 400, height - 30)
def keyPressed():
global gameState, countdownStarted
if key == 'p' or key == 'P':
if gameState == MAIN_MENU:
gameState = COUNT_DOWN
countdownStarted = True
elif key == 'r' or key == 'R':
#if gameState == RESULT:
gameState = MAIN_MENU
class Car(object):
def __init__(self, tempMaxRev, tempMaxGear, tempFrameToFullRev, tempGoalDistance):
self.spd = 0.0
self.acce = 0.0
self.airRes = 0.0
self.rev = 1000
self.frameToFullRev = tempFrameToFullRev
self.maxRev = tempMaxRev
self.throttle = False
self.blown = False
self.gearSwitch = False
self.gear = 0
self.maxGear = tempMaxGear
self.curDist = 0
self.goalDist = tempGoalDistance
def selfInit(self):
self.spd = 0.0
self.acce = 0.0
self.airRes = 0.0
self.rev = 1000
self.throttle = False
self.blown = False
self.gearSwitch = False
self.gear = 0
self.curDist = 0
def update(self):
# Check if car is blown first
self.checkBlown()
if self.blown:
# if Blown, slowly decrease it's spd till 0
if self.spd < 1:
self.spd = 0
else:
self.spd -= self.spd / 7
else:
self.GearShifting()
self.Calculating()
# Shifting the car's gear
def GearShifting(self):
if self.gearSwitch == True:
if self.gear < self.maxGear:
self.gear += 1
else:
self.rev += self.maxRev / 5
# Calculate Current Acce, spd, distance
def Calculating(self):
if self.throttle:
self.rev += (self.maxRev / self.frameToFullRev) / (self.gear + 1)
# print("Throttle on")
else:
if self.rev > 1000:
self.rev -= (self.maxRev / self.frameToFullRev) / (self.gear + 1) * 2
mappedRev = map(self.rev, 0, self.maxRev, 0, 1)
if self.gear == 0:
engineForce = 0
else:
engineForce = mappedRev * (5 - self.gear)
# print(self.rev, self.maxRev, self.frameToFullRev, self.gear)
# TODO?: Make car move more realistically
# mappedRev = map(self.rev, 0, maxRev, 0, 1)
# engineForce = -0.63 * sq(mappedRev) + 0.47 * mappedRev + 0.76
self.airRes = AIR_COEFF * sq(self.spd)
# self.acce = engineForce - self.airRes
# engineForce = self.rev * self.gear
self.acce = engineForce
self.spd += self.acce
self.curDist += self.spd
def render(self):
self.renderCar()
#self.renderBackground()
def renderCar(self):
global T_Car, T_Tire
imageMode(CENTER)
tempX = map(self.curDist, 0, self.goalDist, 150, width + 150)
tempY = 500
image(T_Car, tempX, tempY)
tireX = map(self.curDist, 0, self.goalDist, 45, width + 45)
tireY = 506
pushMatrix()
translate(tireX, tireY)
if self.spd != 0:
rotate(random(0,PI))
image(T_Tire, 0, 0)
popMatrix()
# This function is useless now
# def renderBackground(self):
# global T_BG1, T_BG2, T_MG1, T_MG2, T_FG1, T_FG2
# imageMode(CENTER)
# bgPosX = map(self.goalDist - self.curDist, 0, self.goalDist, 0, 1792 * 2) % (1792 * 2) + (1792 / 2)
# bgPosY = 200
# image(T_BG1, bgPosX - 400, bgPosY)
# image(T_BG2, bgPosX + 1792 - 400, bgPosY)
def checkBlown(self):
if self.rev > self.maxRev:
self.blown = True
class CityBackground(object):
def __init__(self, tempImgA, tempImgB, tempY, tempCar, tempSpdCoeff):
self.imgA = tempImgA
self.imgB = tempImgB
self.spd = 0
self.imgHeight = tempY
self.imgAX = 0
self.imgBX = 1792
self.car = tempCar
self.spdCoe = tempSpdCoeff
def update(self):
self.spd = int(self.car.spd / self.spdCoe)
if self.imgAX < -1 * (1792):
self.imgAX += 1792 * 2
self.imgAX -= self.spd
if self.imgBX < -1 * (1792):
self.imgBX += 1792 * 2
self.imgBX -= self.spd
def render(self):
imageMode(CORNER)
image(self.imgA, self.imgAX, self.imgHeight)
image(self.imgB, self.imgBX, self.imgHeight)
class Particle:
def __init__(self, tempX, tempY, tempSpd, tempLife):
#print(30)
self.initialX = tempX
self.initialY = tempY
self.position = PVector(tempX, tempY)
self.velocity = PVector(random(tempSpd, tempSpd / 3), 0)
self.amplitude = random(5, 20)
self.angle = 0
self.angleVelocity = random(tempSpd/100, tempSpd/30)
self.trail = []
self.lifespan = int(random(tempLife - tempLife/10, tempLife + tempLife+10))
#print(25)
def update(self):
self.position.x += self.velocity.x
self.position.y = self.initialY + self.amplitude * sin(self.angle)
self.angle += self.angleVelocity
self.trail.append(self.position.copy())
if len(self.trail) > 20:
self.trail.pop(0)
self.lifespan -= 1
def render(self):
if self.lifespan > 0:
noFill()
opacity = map(self.lifespan, 0, 200, 0, 255)
stroke(255, opacity)
for i in range(1, len(self.trail)):
p1 = self.trail[i - 1]
p2 = self.trail[i]
segmentRatio = float(i) / len(self.trail)
if segmentRatio < 0.5:
width = map(segmentRatio, 0, 0.5, 0.5, 3)
else:
width = map(segmentRatio, 0.5, 1, 3, 0.5)
angle = atan2(p2.y - p1.y, p2.x - p1.x) + HALF_PI
xOff = width * cos(angle)
yOff = width * sin(angle)
beginShape()
vertex(p1.x + xOff, p1.y + yOff)
vertex(p1.x - xOff, p1.y - yOff)
vertex(p2.x - xOff, p2.y - yOff)
vertex(p2.x + xOff, p2.y + yOff)
endShape(CLOSE)
Screenshot

Download
Download
application.windows64.zip 44 MB
Install instructions
Java 8 required

Leave a comment
Log in with itch.io to leave a comment.