Spent majority of the weekend participating in Ludum Dare, the theme for which was “Enemies as Weapons”
More details later, but for now, a download link:
Ludum Dare entry page: Sporg
sporg_ld48_release.zip (4407KB).
Spent majority of the weekend participating in Ludum Dare, the theme for which was “Enemies as Weapons”
More details later, but for now, a download link:
Ludum Dare entry page: Sporg
sporg_ld48_release.zip (4407KB).
In reverse pong, you score points by allowing the ‘ball’ to pass into your own goal, rather than defending your goal as in traditional pong. The score value of the ball is doubled each time it is reflected by a player, and the scores of both players diminish by a percentage each time at each reflection.
Rather than focusing on traditional game skills such as reflex and dexterity, Reverse Pong is instead a bluffing game of mental misdirection and brinksmanship which attempts to pit the personalities, rather than the skills, of the two players into conflict.
import random
import pygame
#revpong
#pong clone
#players score points by allowing the pong ball into their own goal
#every paddle deflection doubles the current ball value
pygame.init()
pygame.display.set_caption("Revpong")
screen = pygame.display.set_mode((800, 480), pygame.FULLSCREEN)
pygame.mouse.set_visible(False)
#screen = pygame.display.set_mode((800, 480))
windowsize = screen.get_size()
gameContinue = True
game_colour = (255, 255, 255)
clock = pygame.time.Clock()
font = pygame.font.SysFont(pygame.font.get_default_font(), 36)
paddle_dimensions = (24, 96)
paddle = pygame.surface.Surface(paddle_dimensions)
paddle.fill(game_colour)
ball = pygame.surface.Surface((24, 24))
ball.fill(game_colour)
ball_position = (windowsize[0]/2, windowsize[1]/2)
ball_velocity = (-4, 4)
#x positions of paddles
paddle_x_1 = paddle_dimensions[0] * 3
paddle_x_2 = windowsize[0] - paddle_dimensions[0] * 4
#y positions of paddles
paddle_y_1 = windowsize[1] / 2 - paddle_dimensions[1] / 2
paddle_y_2 = windowsize[1] / 2 - paddle_dimensions[1] / 2
#deltas of paddles
paddle_d_1 = 0
paddle_d_2 = 0
#scores
score_ball = 1
score_1 = 0
score_2 = 0
def reset_ball(ball_position, ball_velocity):
random_y = int(random.random() * 5) - int(random.random() * 5)
random_x = 2 + int(random.random() * 2)
ball_position = windowsize[0]/2, windowsize[1]/2
if score_1 > score_2:
ball_velocity = random_x, random_y
elif score_2 > score_1:
ball_velocity = -random_x, random_y
else:
if random.random() > 0.5:
ball_velocity = random_x, random_y
else:
ball_velocity = -random_x, random_y
return ball_position, ball_velocity
ball_position, ball_velocity = reset_ball(ball_position, ball_velocity)
while gameContinue:
clock.tick(50)
for event in pygame.event.get():
if event.type == pygame.QUIT:
gameContinue = False
#input
keys = pygame.key.get_pressed()
paddle_d_1 = 0
paddle_d_2 = 0
if keys[pygame.K_ESCAPE]:
gameContinue = False
if keys[pygame.K_w]:
paddle_y_1 -= 4
paddle_d_1 -= 1
if keys[pygame.K_s]:
paddle_y_1 += 4
paddle_d_1 += 1
if keys[pygame.K_o]:
paddle_y_2 -= 4
paddle_d_2 -= 1
if keys[pygame.K_l]:
paddle_y_2 += 4
paddle_d_1 += 1
ball_old_position = ball_position
ball_position = ball_position[0] + ball_velocity[0], ball_position[1] + ball_velocity[1]
#check new ball_position for collision with top and bottom edges
if ball_position[1] < 12 or ball_position[1] > windowsize[1] - 12:
#bounce off top or bottom edge
ball_position = ball_old_position
ball_velocity = (ball_velocity[0], -ball_velocity[1])
#check new ball_position for collision with score zones
if ball_position[0] < paddle_dimensions[0]:
#player 1 scores
ball_position, ball_velocity = reset_ball(ball_position, ball_velocity)
score_1 += score_ball
score_ball = 1
if ball_position[0] > windowsize[0] - paddle_dimensions[0]:
#player 2 scores
score_2 += score_ball
score_ball = 1
ball_position, ball_velocity = reset_ball(ball_position, ball_velocity)
ball_rect = pygame.Rect((ball_position[0] - 12, ball_position[1] - 12), (24, 24))
#check new ball_position for collision with paddle_1
paddle_rect = pygame.Rect((paddle_x_1, paddle_y_1), paddle_dimensions)
if ball_rect.colliderect(paddle_rect):
#if the ball has passed the paddle x middle
if ball_position[0] < paddle_x_1 + paddle_dimensions[0]/2:
#test if ball is up or down
if ball_position[1] < paddle_y_1 + paddle_dimensions[1]:
#ball is up
ball_velocity = ball_velocity[0], ball_velocity[1] - 4
else:
#ball is down
ball_velocity = ball_velocity[0], ball_velocity[1] + 4
else:
ball_velocity = ball_velocity[0] * -1 + 0.1, ball_velocity[1] + paddle_d_1
ball_position = paddle_x_1 + paddle_dimensions[0] + 12 + ball_velocity[0], ball_position[1] + ball_velocity[1]
score_ball = score_ball * 2
score_1 = int(score_1 * 0.90)
score_2 = int(score_2 * 0.90)
paddle_rect = pygame.Rect((paddle_x_2, paddle_y_2), paddle_dimensions)
if ball_rect.colliderect(paddle_rect):
#if the ball has passed the paddle x middle
if ball_position[0] > paddle_x_2 + paddle_dimensions[0]:
#test if ball is up or down
if ball_position[1] < paddle_y_2 + paddle_dimensions[1] / 2:
#ball is up
ball_velocity = ball_velocity[0], ball_velocity[1] - 4
else:
#ball is down
ball_velocity = ball_velocity[0], ball_velocity[1] + 4
else:
ball_velocity = ball_velocity[0] * -1 - 0.1, ball_velocity[1] + paddle_d_2
ball_position = paddle_x_2 - 12 + ball_velocity[0], ball_position[1] + ball_velocity[1]
score_ball = score_ball * 2
score_1 = int(score_1 * 0.90)
score_2 = int(score_2 * 0.90)
#draw
screen.fill((0,0,0))
screen.blit(paddle, (paddle_x_1, paddle_y_1))
screen.blit(paddle, (paddle_x_2, paddle_y_2))
screen.blit(ball, (ball_position[0] - 12, ball_position[1] - 12))
screen.blit(font.render(str(score_1), False, game_colour), (0,0))
offset = font.size(str(score_2))
screen.blit(font.render(str(score_2), False, game_colour), (windowsize[0]-offset[0],0))
offset = font.size(str(score_ball))
screen.blit(font.render(str(score_ball), False, game_colour), (windowsize[0]/2 - offset[0]/2, windowsize[1]-offset[1]))
pygame.display.flip()
Our Ninjar exists in perfect Ninjar tranquility, upon a finite plane of austere Zen contemplation. Only the incessant, infinite flights of confetti filled combustible birds mar this ultimate Ninjar existence. Armed only with his flying kick of compassion, our Ninjar may attempt to rid the sky of these airborne abominations, but ultimately must come to realise that external actions are meaningless and true Zen is found only by acting on the world within.
(Unoptimised PyGame example)
Download Ninjar (requires Python, Pygame)
Python source:
#Ninjar 11:04 AM 19/03/2010
import sys, random
import pygame
from pygame.locals import *
class Ninja:
def __init__(self, sprites):
self.sprites = sprites #sprite array
self.x = 400
self.y_offset = 400 #height from floor. POSITIVE IS UP
self.baseFrame = 0 #animation cycle baseframe
self.f = 0 #frame to use to draw this char
self.yImpulse = 0 #jump impulse
self.health = 10
self.vx = 0 #x momentum
self.facing = True #True is right, False is left
self.control_x = 0 #-1 = left, 0 = neutral, 1 = right
self.control_jump = False #0 = not jumping, #1 = trying to jump
self.control_attack = False
self.control_duck = False
self.timer_attack = 0 #time until can attack again
self.attacking = False
def tick(self):
#See if we need to update the facing position and x velocity
#when airborne we have less control over x
if self.control_x == -1: #heading left
self.facing = False
if self.y_offset > 0:
self.vx -= 1
else:
self.vx -= 3
self.baseFrame += 1
elif self.control_x == 1: #heading right
self.facing = True
if self.y_offset > 0:
self.vx += 1
else:
self.vx += 3
self.baseFrame += 1
else: #not actively running, slow down a bit
if self.vx > 0:
self.vx = max(0, self.vx - 2)
if self.vx < 0:
self.vx = min(0, self.vx + 2)
self.baseFrame = 0
#Are we airborne?
if self.y_offset > 0:
if self.attacking:
if self.facing:
self.f = 1 #kick right
else:
self.f = 12 #kick left
else:
if self.facing:
self.f = 0 #duck right
else:
self.f = 11 #duck left
#Are we trying to attack?
if self.control_attack and not self.timer_attack:
self.timer_attack = 10
self.attacking = True
if self.facing:
self.f = 1 #kick right
else:
self.f = 12 #kick left
#Are we still going up?
if self.yImpulse > 0:
#slow down a bit
self.yImpulse -= 1
self.y_offset += self.yImpulse
else: #Gravity time
self.y_offset = max(self.y_offset - 8, 0)
else: #we're not airborne, consider ground options
self.attacking = False #we're not attacking if we're on the ground
if self.control_duck: #if we're trying to duck
if self.facing:
self.f = 0 #duck right
else:
self.f = 11 #duck left
#skid to a halt
if self.vx > 0:
self.vx = max(0, self.vx - 3)
if self.vx < 0:
self.vx = min(0, self.vx + 3)
elif self.control_jump: #we're trying to jump?
self.yImpulse = 24
self.y_offset = 16
else:
self.f = self.baseFrame % 9 + 2
if not self.facing:
self.f += 11
#attack timer countdown
self.timer_attack = max(self.timer_attack - 1, 0)
#impose maximum horizontal velocity
if self.vx > 0:
self.vx = min(9, self.vx)
if self.vx < 0:
self.vx = max(-9, self.vx)
self.x += self.vx
if self.x > 850:
self.x = -25
if self.x < -25:
self.x = 825
def draw(self, surface):
surface.blit(self.sprites[self.f], (self.x, 364 - self.y_offset))
class Ninjar:
def __init__(self):
self.size = 800, 480 #set screen dimensions
pygame.init() #start pygame
pygame.mouse.set_visible(False)
#Set up the screen
pygame.display.set_caption("NINJAR 0")
self.surface = pygame.display.set_mode(self.size, pygame.FULLSCREEN)
self.background = pygame.image.load("sprites/background.png")
#Set up game clock for framerate control
self.clock = pygame.time.Clock()
#Load sprites
#Red sprites 0=duck right, 1=kick right 2->10=walk right, 11=duck left, 12 = kick right, 13->22=walk left
self.redSprites = []
duckSprite = pygame.image.load("sprites/ninja_red_r_duck.png").convert_alpha()
kickSprite = pygame.image.load("sprites/ninja_red_r_kick.png").convert_alpha()
self.redSprites.append(duckSprite)
self.redSprites.append(kickSprite)
for i in range(0,9):
walkSprite = pygame.image.load("sprites/ninja_red_r_"+str(i)+".png").convert_alpha()
self.redSprites.append(walkSprite)
#Mirror loaded sprites for left frames
for i in range(len(self.redSprites)):
walkSprite = pygame.transform.flip(self.redSprites[i], True, False)
self.redSprites.append(walkSprite)
self.redNinja = Ninja(self.redSprites)
self.ninjas = []
self.ninjas.append(self.redNinja)
#set us up the birdies
self.birds = []
self.birdFrames = []
for i in range(6):
frame = pygame.Surface((12, abs(3 - i)*3+1))
frame.fill((200, 200, 200))
self.birdFrames.append(frame)
self.birdBlood = pygame.Surface((6,6))
self.birdBlood.fill((255,64,64))
self.gibs = []
self.deathzone = pygame.Rect(0,0,0,0)
def createBird(self):
self.birds.append([-3.0,150.0+100.0*random.random(), int(random.random()*6)])
def createGib(self, x, y):
dx = random.random() * 20 - 10
dy = random.random() * -10
self.gibs.append((x,y,dx,dy))
#Main gameloop
def tick(self):
self.clock.tick(30) #limit framerate to 30 fps
dirtyRects = [] #list of dirty rect areas to update
self.surface.blit(self.background, (0,0)) #redraw background
for ninja in self.ninjas:
rect = (ninja.x, 364 - ninja.y_offset, 16, 64)
dirtyRects.append(rect)
ninja.tick()
rect = (ninja.x, 364 - ninja.y_offset, 16, 64)
dirtyRects.append(rect)
ninja.draw(self.surface)
if ninja.attacking:
xOffset = 24
if not ninja.facing:
xOffset = -3
self.deathzone = pygame.Rect((ninja.x + xOffset,358 - (ninja.y_offset-56)), (20,20))
#add more birds?
if len(self.birds) < 100:
if random.random() > 0.95:
self.createBird()
#Move and draw the birds
for i in range(len(self.birds)):
bird = self.birds[i]
rect = (bird[0], bird[1], 12, 12)
dirtyRects.append(rect)
#Move bird
x = bird[0] + random.random() * 6
if x > self.size[0]:
x = -20
y = bird[1] + random.random()*5 - 2.5
y = max( 110, min(350, y))
f = (bird[2] + 1) % 6
rect = (bird[0], bird[1], 12, 12)
dirtyRects.append(rect)
#test for death
birdRect = pygame.Rect(x,y,12,12)
if birdRect.colliderect(self.deathzone):
gibCount = int(5 + random.random() * 5)
for j in range(gibCount):
self.createGib(x,y)
x = -(10 + random.random()*100)
self.birds[i] = (x, y, f)
#Draw bird
self.surface.blit(self.birdFrames[3], (x+4, y))
self.surface.blit(self.birdFrames[4], (x-2, y))
self.surface.blit(self.birdFrames[f], (x, y))
#handle gibs
for i in range(len(self.gibs)):
gib = self.gibs[i]
rect = (gib[0], gib[1], 6, 6)
dirtyRects.append(rect)
x = gib[0] + gib[2]
y = gib[1] + gib[3]
dx = gib[2] * 0.95
dy = gib[3] + 0.5
self.gibs[i] = (x,y,dx,dy)
rect = (gib[0], gib[1], 6, 6)
dirtyRects.append(rect)
self.surface.blit(self.birdBlood, (x,y))
for gib in self.gibs:
if gib[1] > 420:
self.background.blit(self.birdBlood, (gib[0], gib[1]))
self.gibs.remove(gib)
#handle pygame events
for event in pygame.event.get():
if event.type == pygame.QUIT:
sys.exit()
if event.type == pygame.KEYDOWN:
#Up cursor
if event.key == 273:
self.redNinja.control_jump = True
#Down cursor
if event.key == 274:
self.redNinja.control_duck = True
#Right cursor
if event.key == 275:
self.redNinja.control_x = +1
#Left cursor
if event.key == 276:
self.redNinja.control_x = -1
#Space
if event.key == 32:
self.redNinja.control_attack = True
if event.type == pygame.KEYUP:
#Up cursor
if event.key == 273:
self.redNinja.control_jump = False
#Down cursor
if event.key == 274:
self.redNinja.control_duck = False
#Right cursor
if event.key == 275:
self.redNinja.control_x = 0
#Left cursor
if event.key == 276:
self.redNinja.control_x = 0
#Space
if event.key == 32:
self.redNinja.control_attack = False
#Commit graphical changes to display
#pygame.display.flip()
pygame.display.update(dirtyRects)
app = Ninjar()
while True:
app.tick()
What with twitter, friendfeed, facebook and real life, there’s not a great deal deal left for the personal blog channel.
Update (27/04/2010): Changes in commitments present the opportunity for continued participation in the blogosphere!