SFML/python/samples/worm.py

241 lines
6.4 KiB
Python

#!/usr/bin/python
from PySFML import *
import math
import random
import sys
def Game(Difficulty):
PartsPerFrame = 1 + Difficulty # Number of drawn base parts each frame
PartsSpacing = 3 # Each worm's base part is separated by PartsSpacing pixels
TurnStep = 0.15 # Turn the worm's head of 0.15 rad
PartSize = 6.0 # worm's base part size for collision
PartRealSize = 18.0 # worm's real base part size for drawing
# Load images
Rond = sf.Image() # Image containing the base part of the worm
if not Rond.LoadFromFile("./data/rond2.png"):
print "Could not load data/rond2.png"
return
WormPart = sf.Sprite(Rond)
WormPart.SetCenter(Rond.GetWidth()/2, Rond.GetHeight()/2)
AppleImg = sf.Image() # Apple's image
if not AppleImg.LoadFromFile("./data/apple.png"):
print "Could not load data/apple.png"
return
Apple = sf.Sprite(AppleImg, 0, 0, 1, 1, 0) # Corresponding sprite
Black = sf.Color(0,0,0,255)
UglyYellow = sf.Color(220, 220, 20, 255)
Stop = False
Event = sf.Event() # Our events manager
Level = 0
ShrinkValue = 20
Border = 30
ArenaTop = 20
ArenaBottom = 520
RequiredLength = 300
ExitLeft = 350
ExitRight = 450
ExitImg = sf.Image(ExitRight-ExitLeft, ArenaTop, Black)
Exit = sf.Sprite(ExitImg, ExitLeft, 0, 1, 1, 0)
Score = 0
HeadX, HeadY = 0, 0
while not Stop:
#Initialize a new game
Level += 1
ArenaLeft = ShrinkValue*Level
ArenaRight = 800-ShrinkValue*Level
ArenaImg = sf.Image(ArenaRight-ArenaLeft, ArenaBottom-ArenaTop, Black)
Arena = sf.Sprite(ArenaImg, ArenaLeft, ArenaTop, 1, 1, 0)
AppleX, AppleY = random.randrange(ArenaLeft+Border, ArenaRight-Border), random.randrange(ArenaTop+Border, ArenaBottom-Border)
Apple.SetX(AppleX - AppleImg.GetWidth()/2) # We move the apple to somewhere else, randomly
Apple.SetY(AppleY - AppleImg.GetHeight()/2)
Crash = False
Running = True
LevelStr = sf.String("Level: " + str(Level))
LevelStr.SetPosition(60., 540.)
LevelStr.SetColor(UglyYellow)
ScoreStr = sf.String("Score: 0")
ScoreStr.SetPosition(260., 540.)
ScoreStr.SetColor(UglyYellow)
Length = 1
TargetedLength = 30
Worm = [[ArenaLeft+50., ArenaTop+50.]]
Angle = 0
i = 0
Dir = 0
while Running: # Game main loop
while App.GetEvent(Event): # Event Handler
if Event.Type == sf.Event.Closed:
App.Close()
return
if Event.Type == sf.Event.KeyPressed:
if Event.Key.Code == sf.Key.Escape:
Running = False
Stop = True
if Event.Key.Code == sf.Key.Left:
Dir = -1
if Event.Key.Code == sf.Key.Right:
Dir = 1
if Crash and Length<=1:
Running = False
if Event.Type == sf.Event.KeyReleased:
if Event.Key.Code == sf.Key.Left and Dir == -1:
Dir = 0
if Event.Key.Code == sf.Key.Right and Dir == 1:
Dir = 0
App.Draw(Arena)
if not Crash: # Create new parts and check collisions if the worm hasn't crashed yet
for i in range(0, PartsPerFrame): # We create PartsPerFrame Worm's parts
Angle += Dir*TurnStep
HeadX, HeadY = Worm[Length-1][0]+PartsSpacing*math.cos(Angle), Worm[Length-1][1]+PartsSpacing*math.sin(Angle)
if TargetedLength <= RequiredLength:
if math.sqrt ( (AppleX - HeadX)**2 + (AppleY - HeadY)**2 ) < 14 + PartSize/2: # The Worm ate the apple
Score += 1
TargetedLength += 20 # The worm gets longer
if TargetedLength <= RequiredLength:
AppleX, AppleY = random.randrange(ArenaLeft+Border, ArenaRight-Border), random.randrange(ArenaTop+Border, ArenaBottom-Border)
Apple.SetX(AppleX - AppleImg.GetWidth()/2) # We move the apple to somewhere else, randomly
Apple.SetY(AppleY - AppleImg.GetHeight()/2)
App.Draw(Apple)
if HeadX<ArenaLeft+PartSize/2 or HeadX>ArenaRight-PartSize/2 or HeadY<ArenaTop+PartSize/2 or HeadY>ArenaBottom-PartSize/2: # Crash into a wall
if Length > RequiredLength:
if HeadY<ArenaTop+PartSize/2:
if HeadX<ExitLeft+PartSize/2 or HeadX>ExitRight-PartSize/2:
Crash = True
elif HeadY < 0:
Length = 0
Running = False # Level completed!
else:
Crash = True
elif Running:
Crash = True
if not Crash:
Worm.append([HeadX, HeadY])
Length += 1
if TargetedLength > RequiredLength:
App.Draw(Exit)
if Length >= TargetedLength:
Worm[0:TargetedLength] = Worm[Length-TargetedLength:Length]
for i in range(Length, TargetedLength):
del Worm[i]
Worm[TargetedLength:Length] = []
Length = TargetedLength
for i in range(0, Length):
WormPart.SetPosition(Worm[i][0], Worm[i][1])
App.Draw(WormPart) # Draw the part on screen
if i < Length - PartSize/PartsSpacing - 1:
if math.sqrt( (HeadX-Worm[i][0])**2 + (HeadY-Worm[i][1])**2 ) < PartSize and Running: # Check for collision
Crash = True
if Crash and Length>0:
TargetedLength -= PartsPerFrame
ScoreStr.SetText("Score: " + str(Score))
App.Draw(ScoreStr)
App.Draw(LevelStr)
App.Display() # Refresh Screen
App.Clear(BGColor)
# End of the game
if Crash:
Level = 0
Score = 0
else:
Score += 5 # End level bonus
del Worm
del Arena
del ArenaImg
def Menu():
Selection = 0
TextColor = sf.Color(220, 220, 20, 255)
Running = True
Event = sf.Event()
Title = sf.String("PyWorm!")
Title.SetX(320.)
Title.SetY(50.)
Title.SetColor(TextColor)
Levels = ["Very Easy", "Easy", "Medium", "Hard"]
Xs = [320., 350., 330., 350.]
Strings = [0,0,0,0]
for i in range(0, 4):
Strings[i] = sf.String(Levels[i])
Strings[i].SetColor(TextColor)
Strings[i].SetPosition(Xs[i], 200. + 80*i)
RectangleImg = sf.Image(ScreenWidth, 40, sf.Color(50,50,10,255))
Rectangle = sf.Sprite(RectangleImg, 0, 350, 1, 1, 0)
while App.IsOpened(): # Game main loop
while App.GetEvent(Event): # Event Handler
if Event.Type == sf.Event.Closed:
App.Close()
if Event.Type == sf.Event.KeyPressed:
if Event.Key.Code == sf.Key.Escape:
App.Close()
elif Event.Key.Code == sf.Key.Up:
Selection = (Selection - 1) % 4
elif Event.Key.Code == sf.Key.Down:
Selection = (Selection + 1) % 4
elif Event.Key.Code == sf.Key.Return:
Game(Selection)
Rectangle.SetY(200 + Selection*80)
App.Draw(Rectangle)
App.Draw(Title)
for i in range(0,4):
App.Draw(Strings[i])
App.Display()
App.Clear(BGColor)
# Initialize the window
ScreenWidth, ScreenHeight = 800, 600
App = sf.RenderWindow(sf.VideoMode(ScreenWidth,ScreenHeight,32), "PyWorm", sf.Style.Close) # Creates the window
BGColor = sf.Color(100,100,0,255)
App.SetFramerateLimit(30)
Menu()