9
.gitignore
vendored
@ -1,4 +1,9 @@
|
|||||||
# Cache after running the app
|
<<<<<<< HEAD
|
||||||
__pycache__/
|
# ignore debug
|
||||||
out/
|
out/
|
||||||
build/
|
build/
|
||||||
|
.vscode/
|
||||||
|
__pycache__/
|
||||||
|
*/__pycache__/
|
||||||
|
# ignore test
|
||||||
|
test.py
|
||||||
|
|||||||
14
main.py
@ -1,7 +1,15 @@
|
|||||||
#!/usr/bin/env python
|
#!/usr/bin/env python
|
||||||
import pygame as pg
|
import pygame as pg
|
||||||
from source.main import main
|
from source import tool
|
||||||
|
from source import constants as c
|
||||||
|
from source.state import mainmenu, screen, level
|
||||||
|
|
||||||
if __name__=='__main__':
|
if __name__=='__main__':
|
||||||
main()
|
# 控制状态机运行
|
||||||
pg.quit()
|
game = tool.Control()
|
||||||
|
state_dict = {c.MAIN_MENU: mainmenu.Menu(),
|
||||||
|
c.GAME_VICTORY: screen.GameVictoryScreen(),
|
||||||
|
c.GAME_LOSE: screen.GameLoseScreen(),
|
||||||
|
c.LEVEL: level.Level()}
|
||||||
|
game.setup_states(state_dict, c.MAIN_MENU)
|
||||||
|
game.run()
|
||||||
|
|||||||
90
resources/about.drawio
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
<mxfile host="65bd71144e" modified="2020-11-30T06:16:32.395Z" agent="5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Code/1.51.1 Chrome/83.0.4103.122 Electron/9.3.3 Safari/537.36" etag="RC1RIFtEJiW45I55AWKe" version="13.6.5" pages="2">
|
||||||
|
<diagram id="FslXHE_8ykSBRjm2p2tr" name="第 1 页">
|
||||||
|
<mxGraphModel dx="724" dy="461" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="3300" pageHeight="4681" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="0"/>
|
||||||
|
<mxCell id="1" parent="0"/>
|
||||||
|
<mxCell id="2" value="mainmenu" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="140" y="210" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="3" value="level" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="420" y="150" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="4" value="game over" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="680" y="210" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="5" value="little games" style="rounded=1;whiteSpace=wrap;html=1;" parent="1" vertex="1">
|
||||||
|
<mxGeometry x="420" y="270" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="6" value="" style="shape=flexArrow;endArrow=classic;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="2" target="3" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="580" y="360" as="sourcePoint"/>
|
||||||
|
<mxPoint x="630" y="310" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="7" value="" style="shape=flexArrow;endArrow=classic;html=1;exitX=1.025;exitY=0.867;exitDx=0;exitDy=0;exitPerimeter=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="2" target="5" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="290" y="340" as="sourcePoint"/>
|
||||||
|
<mxPoint x="340" y="290" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="9" value="" style="shape=flexArrow;endArrow=classic;html=1;exitX=1;exitY=0.5;exitDx=0;exitDy=0;entryX=0;entryY=0.5;entryDx=0;entryDy=0;" parent="1" source="3" target="4" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="580" y="200" as="sourcePoint"/>
|
||||||
|
<mxPoint x="630" y="150" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="10" value="" style="shape=flexArrow;endArrow=classic;html=1;entryX=0;entryY=0.5;entryDx=0;entryDy=0;exitX=1;exitY=0.5;exitDx=0;exitDy=0;" parent="1" source="5" target="4" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="630" y="330" as="sourcePoint"/>
|
||||||
|
<mxPoint x="680" y="280" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="11" value="" style="shape=flexArrow;endArrow=classic;html=1;exitX=0.5;exitY=0;exitDx=0;exitDy=0;entryX=0.5;entryY=0;entryDx=0;entryDy=0;" parent="1" source="4" target="2" edge="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="720" y="150" as="sourcePoint"/>
|
||||||
|
<mxPoint x="260" y="50" as="targetPoint"/>
|
||||||
|
<Array as="points">
|
||||||
|
<mxPoint x="530" y="70"/>
|
||||||
|
</Array>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="1ls8mGlj3wdy2eXAvnXn-11" value="control" style="rounded=1;whiteSpace=wrap;html=1;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="140" y="390" width="120" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="1ls8mGlj3wdy2eXAvnXn-12" value="" style="shape=flexArrow;endArrow=classic;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;exitX=0.5;exitY=0;exitDx=0;exitDy=0;" edge="1" parent="1" source="1ls8mGlj3wdy2eXAvnXn-11" target="2">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="180" y="370" as="sourcePoint"/>
|
||||||
|
<mxPoint x="230" y="320" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="1ls8mGlj3wdy2eXAvnXn-13" value="" style="endArrow=none;dashed=1;html=1;dashPattern=1 3;strokeWidth=2;" edge="1" parent="1">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="80" y="470" as="sourcePoint"/>
|
||||||
|
<mxPoint x="815.3333740234375" y="470" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="1ls8mGlj3wdy2eXAvnXn-14" value="" style="shape=flexArrow;endArrow=classic;html=1;entryX=0.5;entryY=1;entryDx=0;entryDy=0;" edge="1" parent="1" target="1ls8mGlj3wdy2eXAvnXn-11">
|
||||||
|
<mxGeometry width="50" height="50" relative="1" as="geometry">
|
||||||
|
<mxPoint x="200" y="560" as="sourcePoint"/>
|
||||||
|
<mxPoint x="200" y="500" as="targetPoint"/>
|
||||||
|
</mxGeometry>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="1ls8mGlj3wdy2eXAvnXn-15" value="Actor" style="shape=umlActor;verticalLabelPosition=bottom;verticalAlign=top;html=1;outlineConnect=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="260" y="550" width="30" height="60" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
<mxCell id="1ls8mGlj3wdy2eXAvnXn-16" value="input" style="text;html=1;strokeColor=none;fillColor=none;align=center;verticalAlign=middle;whiteSpace=wrap;rounded=0;" vertex="1" parent="1">
|
||||||
|
<mxGeometry x="220" y="510" width="40" height="20" as="geometry"/>
|
||||||
|
</mxCell>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
<diagram id="CydbNID2VFdMlwzW122j" name="Page-2">
|
||||||
|
<mxGraphModel dx="724" dy="461" grid="1" gridSize="10" guides="1" tooltips="1" connect="1" arrows="1" fold="1" page="1" pageScale="1" pageWidth="827" pageHeight="1169" math="0" shadow="0">
|
||||||
|
<root>
|
||||||
|
<mxCell id="-akz3d4JWGbzF8o_4E1M-0"/>
|
||||||
|
<mxCell id="-akz3d4JWGbzF8o_4E1M-1" parent="-akz3d4JWGbzF8o_4E1M-0"/>
|
||||||
|
</root>
|
||||||
|
</mxGraphModel>
|
||||||
|
</diagram>
|
||||||
|
</mxfile>
|
||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"background_type":0,
|
"background_type":0,
|
||||||
"init_sun_value":500,
|
"init_sun_value":500,
|
||||||
|
"shovel":1,
|
||||||
"zombie_list":[
|
"zombie_list":[
|
||||||
{"time":1000, "map_y":2, "name":"Zombie"}
|
{"time":1000, "map_y":2, "name":"Zombie"}
|
||||||
]
|
]
|
||||||
20
resources/data/map/level_1.json
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"background_type": 0,
|
||||||
|
"init_sun_value": 50,
|
||||||
|
"shovel": 1,
|
||||||
|
"zombie_list": [
|
||||||
|
{ "time": 20000, "map_y": 0, "name": "Zombie" },
|
||||||
|
{ "time": 40000, "map_y": 2, "name": "FlagZombie" },
|
||||||
|
{ "time": 50000, "map_y": 4, "name": "Zombie" },
|
||||||
|
{ "time": 70000, "map_y": 3, "name": "Zombie" },
|
||||||
|
{ "time": 72000, "map_y": 1, "name": "FlagZombie" },
|
||||||
|
{ "time": 74000, "map_y": 2, "name": "Zombie" },
|
||||||
|
{ "time": 90000, "map_y": 0, "name": "Zombie" },
|
||||||
|
{ "time": 91000, "map_y": 1, "name": "FlagZombie" },
|
||||||
|
{ "time": 92000, "map_y": 2, "name": "Zombie" },
|
||||||
|
{ "time": 93000, "map_y": 3, "name": "FlagZombie" },
|
||||||
|
{ "time": 94000, "map_y": 0, "name": "Zombie" },
|
||||||
|
{ "time": 95000, "map_y": 4, "name": "FlagZombie" },
|
||||||
|
{ "time": 96000, "map_y": 1, "name": "Zombie" }
|
||||||
|
]
|
||||||
|
}
|
||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"background_type":0,
|
"background_type":0,
|
||||||
"init_sun_value":50,
|
"init_sun_value":50,
|
||||||
|
"shovel":1,
|
||||||
"zombie_list":[
|
"zombie_list":[
|
||||||
{"time":20000, "map_y":0, "name":"Zombie"},
|
{"time":20000, "map_y":0, "name":"Zombie"},
|
||||||
{"time":40000, "map_y":2, "name":"FlagZombie"},
|
{"time":40000, "map_y":2, "name":"FlagZombie"},
|
||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"background_type":1,
|
"background_type":1,
|
||||||
"init_sun_value":50,
|
"init_sun_value":50,
|
||||||
|
"shovel":1,
|
||||||
"zombie_list":[
|
"zombie_list":[
|
||||||
{"time":20000, "map_y":0, "name":"Zombie"},
|
{"time":20000, "map_y":0, "name":"Zombie"},
|
||||||
{"time":40000, "map_y":2, "name":"ConeheadZombie"},
|
{"time":40000, "map_y":2, "name":"ConeheadZombie"},
|
||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"background_type":0,
|
"background_type":0,
|
||||||
"choosebar_type":1,
|
"choosebar_type":1,
|
||||||
|
"shovel":1,
|
||||||
"card_pool":[
|
"card_pool":[
|
||||||
{"name":"Peashooter"},
|
{"name":"Peashooter"},
|
||||||
{"name":"SnowPea"},
|
{"name":"SnowPea"},
|
||||||
@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"background_type":4,
|
"background_type":4,
|
||||||
"choosebar_type":2,
|
"choosebar_type":2,
|
||||||
|
"shovel":0,
|
||||||
"card_pool":[
|
"card_pool":[
|
||||||
{"name":"WallNutBowling"},
|
{"name":"WallNutBowling"},
|
||||||
{"name":"RedWallNutBowling"}
|
{"name":"RedWallNutBowling"}
|
||||||
BIN
resources/graphics/Screen/bigMenu.png
Normal file
|
After Width: | Height: | Size: 233 KiB |
BIN
resources/graphics/Screen/exit.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
resources/graphics/Screen/littleGameButton.png
Normal file
|
After Width: | Height: | Size: 41 KiB |
BIN
resources/graphics/Screen/littleMenu.png
Normal file
|
After Width: | Height: | Size: 3.7 KiB |
BIN
resources/graphics/Screen/mainMenuButton.png
Normal file
|
After Width: | Height: | Size: 10 KiB |
BIN
resources/graphics/Screen/restartButton.png
Normal file
|
After Width: | Height: | Size: 11 KiB |
BIN
resources/graphics/Screen/returnButton.png
Normal file
|
After Width: | Height: | Size: 45 KiB |
BIN
resources/graphics/Screen/shovel.png
Normal file
|
After Width: | Height: | Size: 9.2 KiB |
BIN
resources/graphics/Screen/shovelBox.png
Normal file
|
After Width: | Height: | Size: 7.9 KiB |
BIN
resources/huawen.TTF
Normal file
@ -1,5 +1,4 @@
|
|||||||
__author__ = 'wszqkzqk'
|
__author__ = 'wszqkzqk'
|
||||||
|
|
||||||
import random
|
import random
|
||||||
import pygame as pg
|
import pygame as pg
|
||||||
from .. import tool
|
from .. import tool
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
__author__ = 'wszqkzqk'
|
__author__ = 'wszqkzqk'
|
||||||
|
import os
|
||||||
import random
|
import random
|
||||||
import pygame as pg
|
import pygame as pg
|
||||||
from .. import tool
|
from .. import tool
|
||||||
@ -28,7 +28,9 @@ plant_frozen_time_list = [7500, 7500, 7500, 30000, 50000, 7500, 7500, 7500, 7500
|
|||||||
all_card_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
all_card_list = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16]
|
||||||
|
|
||||||
def getSunValueImage(sun_value):
|
def getSunValueImage(sun_value):
|
||||||
font = pg.font.SysFont(None, 22)
|
# for pack, must use other ttf
|
||||||
|
fontPath = os.path.join('resources', 'huawen.TTF')
|
||||||
|
font = pg.font.Font(fontPath, 14)
|
||||||
width = 32
|
width = 32
|
||||||
msg_image = font.render(str(sun_value), True, c.NAVYBLUE, c.LIGHTYELLOW)
|
msg_image = font.render(str(sun_value), True, c.NAVYBLUE, c.LIGHTYELLOW)
|
||||||
msg_rect = msg_image.get_rect()
|
msg_rect = msg_image.get_rect()
|
||||||
@ -216,6 +218,7 @@ class MenuBar():
|
|||||||
for card in self.card_list:
|
for card in self.card_list:
|
||||||
card.draw(surface)
|
card.draw(surface)
|
||||||
|
|
||||||
|
# 关卡模式选植物的界面
|
||||||
class Panel():
|
class Panel():
|
||||||
def __init__(self, card_list, sun_value):
|
def __init__(self, card_list, sun_value):
|
||||||
self.loadImages(sun_value)
|
self.loadImages(sun_value)
|
||||||
@ -379,7 +382,7 @@ class MoveBar():
|
|||||||
def __init__(self, card_pool):
|
def __init__(self, card_pool):
|
||||||
self.loadFrame(c.MOVEBAR_BACKGROUND)
|
self.loadFrame(c.MOVEBAR_BACKGROUND)
|
||||||
self.rect = self.image.get_rect()
|
self.rect = self.image.get_rect()
|
||||||
self.rect.x = 90
|
self.rect.x = 20
|
||||||
self.rect.y = 0
|
self.rect.y = 0
|
||||||
|
|
||||||
self.card_start_x = self.rect.x + 8
|
self.card_start_x = self.rect.x + 8
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
__author__ = 'wszqkzqk'
|
__author__ = 'wszqkzqk'
|
||||||
|
|
||||||
import random
|
import random
|
||||||
import pygame as pg
|
import pygame as pg
|
||||||
from .. import tool
|
from .. import tool
|
||||||
@ -213,7 +212,7 @@ class Plant(pg.sprite.Sprite):
|
|||||||
self.changeFrames(self.sleep_frames)
|
self.changeFrames(self.sleep_frames)
|
||||||
|
|
||||||
def setDamage(self, damage, zombie):
|
def setDamage(self, damage, zombie):
|
||||||
if not zombie.losHead:
|
if not zombie.lostHead:
|
||||||
self.health -= damage
|
self.health -= damage
|
||||||
self.hit_timer = self.current_time
|
self.hit_timer = self.current_time
|
||||||
if self.health == 0:
|
if self.health == 0:
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
__author__ = 'wszqkzqk'
|
__author__ = 'wszqkzqk'
|
||||||
|
|
||||||
import pygame as pg
|
import pygame as pg
|
||||||
from .. import tool
|
from .. import tool
|
||||||
from .. import constants as c
|
from .. import constants as c
|
||||||
@ -23,7 +22,7 @@ class Zombie(pg.sprite.Sprite):
|
|||||||
self.health = health
|
self.health = health
|
||||||
self.damage = damage
|
self.damage = damage
|
||||||
self.dead = False
|
self.dead = False
|
||||||
self.losHead = False
|
self.lostHead = False
|
||||||
self.helmet = False
|
self.helmet = False
|
||||||
self.head_group = head_group
|
self.head_group = head_group
|
||||||
|
|
||||||
@ -67,9 +66,9 @@ class Zombie(pg.sprite.Sprite):
|
|||||||
self.freezing()
|
self.freezing()
|
||||||
|
|
||||||
def walking(self):
|
def walking(self):
|
||||||
if (self.losHead and (self.current_time - self.losthead_timer) > self.dead_timer):
|
if (self.lostHead and (self.current_time - self.losthead_timer) > self.dead_timer):
|
||||||
self.setDie()
|
self.setDie()
|
||||||
elif self.health <= c.LOSTHEAD_HEALTH and not self.losHead:
|
elif self.health <= c.LOSTHEAD_HEALTH and not self.lostHead:
|
||||||
self.changeFrames(self.losthead_walk_frames)
|
self.changeFrames(self.losthead_walk_frames)
|
||||||
self.setLostHead()
|
self.setLostHead()
|
||||||
elif self.health <= c.NORMAL_HEALTH and self.helmet:
|
elif self.health <= c.NORMAL_HEALTH and self.helmet:
|
||||||
@ -86,9 +85,9 @@ class Zombie(pg.sprite.Sprite):
|
|||||||
self.rect.x -= self.speed
|
self.rect.x -= self.speed
|
||||||
|
|
||||||
def attacking(self):
|
def attacking(self):
|
||||||
if (self.losHead and (self.current_time - self.losthead_timer) > self.dead_timer):
|
if (self.lostHead and (self.current_time - self.losthead_timer) > self.dead_timer):
|
||||||
self.setDie()
|
self.setDie()
|
||||||
elif self.health <= c.LOSTHEAD_HEALTH and not self.losHead:
|
elif self.health <= c.LOSTHEAD_HEALTH and not self.lostHead:
|
||||||
self.changeFrames(self.losthead_attack_frames)
|
self.changeFrames(self.losthead_attack_frames)
|
||||||
self.setLostHead()
|
self.setLostHead()
|
||||||
elif self.health <= c.NORMAL_HEALTH and self.helmet:
|
elif self.health <= c.NORMAL_HEALTH and self.helmet:
|
||||||
@ -110,9 +109,9 @@ class Zombie(pg.sprite.Sprite):
|
|||||||
pass
|
pass
|
||||||
|
|
||||||
def freezing(self):
|
def freezing(self):
|
||||||
if (self.losHead and (self.current_time - self.losthead_timer) > self.dead_timer):
|
if (self.lostHead and (self.current_time - self.losthead_timer) > self.dead_timer):
|
||||||
self.setDie()
|
self.setDie()
|
||||||
elif self.health <= c.LOSTHEAD_HEALTH and not self.losHead:
|
elif self.health <= c.LOSTHEAD_HEALTH and not self.lostHead:
|
||||||
if self.old_state == c.WALK:
|
if self.old_state == c.WALK:
|
||||||
self.changeFrames(self.losthead_walk_frames)
|
self.changeFrames(self.losthead_walk_frames)
|
||||||
else:
|
else:
|
||||||
@ -123,7 +122,7 @@ class Zombie(pg.sprite.Sprite):
|
|||||||
|
|
||||||
def setLostHead(self):
|
def setLostHead(self):
|
||||||
self.losthead_timer = self.current_time
|
self.losthead_timer = self.current_time
|
||||||
self.losHead = True
|
self.lostHead = True
|
||||||
if self.head_group is not None:
|
if self.head_group is not None:
|
||||||
self.head_group.add(ZombieHead(self.rect.centerx, self.rect.bottom))
|
self.head_group.add(ZombieHead(self.rect.centerx, self.rect.bottom))
|
||||||
|
|
||||||
@ -187,7 +186,7 @@ class Zombie(pg.sprite.Sprite):
|
|||||||
|
|
||||||
if self.helmet:
|
if self.helmet:
|
||||||
self.changeFrames(self.helmet_walk_frames)
|
self.changeFrames(self.helmet_walk_frames)
|
||||||
elif self.losHead:
|
elif self.lostHead:
|
||||||
self.changeFrames(self.losthead_walk_frames)
|
self.changeFrames(self.losthead_walk_frames)
|
||||||
else:
|
else:
|
||||||
self.changeFrames(self.walk_frames)
|
self.changeFrames(self.walk_frames)
|
||||||
@ -201,7 +200,7 @@ class Zombie(pg.sprite.Sprite):
|
|||||||
|
|
||||||
if self.helmet:
|
if self.helmet:
|
||||||
self.changeFrames(self.helmet_attack_frames)
|
self.changeFrames(self.helmet_attack_frames)
|
||||||
elif self.losHead:
|
elif self.lostHead:
|
||||||
self.changeFrames(self.losthead_attack_frames)
|
self.changeFrames(self.losthead_attack_frames)
|
||||||
else:
|
else:
|
||||||
self.changeFrames(self.attack_frames)
|
self.changeFrames(self.attack_frames)
|
||||||
@ -278,7 +277,7 @@ class NormalZombie(Zombie):
|
|||||||
|
|
||||||
self.frames = self.walk_frames
|
self.frames = self.walk_frames
|
||||||
|
|
||||||
|
# 路障僵尸
|
||||||
class ConeHeadZombie(Zombie):
|
class ConeHeadZombie(Zombie):
|
||||||
def __init__(self, x, y, head_group):
|
def __init__(self, x, y, head_group):
|
||||||
Zombie.__init__(self, x, y, c.CONEHEAD_ZOMBIE, c.CONEHEAD_HEALTH, head_group)
|
Zombie.__init__(self, x, y, c.CONEHEAD_ZOMBIE, c.CONEHEAD_HEALTH, head_group)
|
||||||
|
|||||||
@ -1,5 +1,4 @@
|
|||||||
__author__ = 'wszqkzqk'
|
__author__ = 'wszqkzqk'
|
||||||
|
|
||||||
START_LEVEL_NUM = 1
|
START_LEVEL_NUM = 1
|
||||||
|
|
||||||
ORIGINAL_CAPTION = 'pypvz'
|
ORIGINAL_CAPTION = 'pypvz'
|
||||||
@ -26,6 +25,22 @@ GREEN = ( 0, 255, 0)
|
|||||||
|
|
||||||
SIZE_MULTIPLIER = 1.3
|
SIZE_MULTIPLIER = 1.3
|
||||||
|
|
||||||
|
# 退出游戏按钮
|
||||||
|
EXIT = 'exit'
|
||||||
|
# 当想要一个特殊值时用
|
||||||
|
NULL = 'null'
|
||||||
|
# 游戏界面可选的菜单
|
||||||
|
LITTLE_MENU = 'littleMenu'
|
||||||
|
BIG_MENU = 'bigMenu'
|
||||||
|
RETURN_BUTTON = 'returnButton'
|
||||||
|
RESTART_BUTTON = 'restartButton'
|
||||||
|
MAINMENU_BUTTON = 'mainMenuButton'
|
||||||
|
LITTLEGAME_BUTTON = 'littleGameButton'
|
||||||
|
# 小铲子
|
||||||
|
SHOVEL = 'shovel'
|
||||||
|
SHOVEL_BOX = 'shovelBox'
|
||||||
|
|
||||||
|
|
||||||
#GAME INFO DICTIONARY KEYS
|
#GAME INFO DICTIONARY KEYS
|
||||||
CURRENT_TIME = 'current time'
|
CURRENT_TIME = 'current time'
|
||||||
LEVEL_NUM = 'level num'
|
LEVEL_NUM = 'level num'
|
||||||
|
|||||||
@ -1,19 +0,0 @@
|
|||||||
{
|
|
||||||
"background_type":0,
|
|
||||||
"init_sun_value":50,
|
|
||||||
"zombie_list":[
|
|
||||||
{"time":20000, "map_y":0, "name":"Zombie"},
|
|
||||||
{"time":40000, "map_y":2, "name":"FlagZombie"},
|
|
||||||
{"time":50000, "map_y":4, "name":"Zombie"},
|
|
||||||
{"time":70000, "map_y":3, "name":"Zombie"},
|
|
||||||
{"time":72000, "map_y":1, "name":"FlagZombie"},
|
|
||||||
{"time":74000, "map_y":2, "name":"Zombie"},
|
|
||||||
{"time":90000, "map_y":0, "name":"Zombie"},
|
|
||||||
{"time":91000, "map_y":1, "name":"FlagZombie"},
|
|
||||||
{"time":92000, "map_y":2, "name":"Zombie"},
|
|
||||||
{"time":93000, "map_y":3, "name":"FlagZombie"},
|
|
||||||
{"time":94000, "map_y":0, "name":"Zombie"},
|
|
||||||
{"time":95000, "map_y":4, "name":"FlagZombie"},
|
|
||||||
{"time":96000, "map_y":1, "name":"Zombie"}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
@ -1,14 +0,0 @@
|
|||||||
__author__ = 'wszqkzqk'
|
|
||||||
|
|
||||||
from . import tool
|
|
||||||
from . import constants as c
|
|
||||||
from .state import mainmenu, screen, level
|
|
||||||
|
|
||||||
def main():
|
|
||||||
game = tool.Control()
|
|
||||||
state_dict = {c.MAIN_MENU: mainmenu.Menu(),
|
|
||||||
c.GAME_VICTORY: screen.GameVictoryScreen(),
|
|
||||||
c.GAME_LOSE: screen.GameLoseScreen(),
|
|
||||||
c.LEVEL: level.Level()}
|
|
||||||
game.setup_states(state_dict, c.MAIN_MENU)
|
|
||||||
game.main()
|
|
||||||
@ -1,5 +1,4 @@
|
|||||||
__author__ = 'wszqkzqk'
|
__author__ = 'wszqkzqk'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
@ -19,16 +18,35 @@ class Level(tool.State):
|
|||||||
self.map_y_len = c.GRID_Y_LEN
|
self.map_y_len = c.GRID_Y_LEN
|
||||||
self.map = map.Map(c.GRID_X_LEN, self.map_y_len)
|
self.map = map.Map(c.GRID_X_LEN, self.map_y_len)
|
||||||
|
|
||||||
|
# 默认显然不用显示菜单
|
||||||
|
self.showLittleMenu = False
|
||||||
|
|
||||||
self.loadMap()
|
self.loadMap()
|
||||||
self.setupBackground()
|
self.setupBackground()
|
||||||
self.initState()
|
self.initState()
|
||||||
|
|
||||||
def loadMap(self):
|
def loadMap(self):
|
||||||
map_file = 'level_' + str(self.game_info[c.LEVEL_NUM]) + '.json'
|
if c.LITTLEGAME_BUTTON in self.game_info:
|
||||||
file_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))), 'source', 'data', 'map', map_file)
|
map_file = 'littleGame_' + str(self.game_info[c.LEVEL_NUM]) + '.json'
|
||||||
f = open(file_path)
|
else:
|
||||||
self.map_data = json.load(f)
|
map_file = 'level_' + str(self.game_info[c.LEVEL_NUM]) + '.json'
|
||||||
f.close()
|
file_path = os.path.join(os.path.dirname(os.path.dirname(os.path.dirname(__file__))),'resources' , 'data', 'map', map_file)
|
||||||
|
# 最后一关之后应该结束了
|
||||||
|
try:
|
||||||
|
f = open(file_path)
|
||||||
|
self.map_data = json.load(f)
|
||||||
|
f.close()
|
||||||
|
except Exception as e:
|
||||||
|
print("游戏结束")
|
||||||
|
f = open(file_path)
|
||||||
|
self.map_data = json.load(f)
|
||||||
|
self.done = True
|
||||||
|
self.next = c.MAIN_MENU
|
||||||
|
return
|
||||||
|
if self.map_data[c.SHOVEL] == 0:
|
||||||
|
self.hasShovel = False
|
||||||
|
else:
|
||||||
|
self.hasShovel = True
|
||||||
|
|
||||||
def setupBackground(self):
|
def setupBackground(self):
|
||||||
img_index = self.map_data[c.BACKGROUND_TYPE]
|
img_index = self.map_data[c.BACKGROUND_TYPE]
|
||||||
@ -40,6 +58,7 @@ class Level(tool.State):
|
|||||||
self.viewport = tool.SCREEN.get_rect(bottom=self.bg_rect.bottom)
|
self.viewport = tool.SCREEN.get_rect(bottom=self.bg_rect.bottom)
|
||||||
self.viewport.x += c.BACKGROUND_OFFSET_X
|
self.viewport.x += c.BACKGROUND_OFFSET_X
|
||||||
|
|
||||||
|
|
||||||
def setupGroups(self):
|
def setupGroups(self):
|
||||||
self.sun_group = pg.sprite.Group()
|
self.sun_group = pg.sprite.Group()
|
||||||
self.head_group = pg.sprite.Group()
|
self.head_group = pg.sprite.Group()
|
||||||
@ -70,6 +89,7 @@ class Level(tool.State):
|
|||||||
_, y = self.map.getMapGridPos(0, i)
|
_, y = self.map.getMapGridPos(0, i)
|
||||||
self.cars.append(plant.Car(-25, y+20, i))
|
self.cars.append(plant.Car(-25, y+20, i))
|
||||||
|
|
||||||
|
# 更新函数每帧被调用,将鼠标事件传入给状态处理函数
|
||||||
def update(self, surface, current_time, mouse_pos, mouse_click):
|
def update(self, surface, current_time, mouse_pos, mouse_click):
|
||||||
self.current_time = self.game_info[c.CURRENT_TIME] = current_time
|
self.current_time = self.game_info[c.CURRENT_TIME] = current_time
|
||||||
if self.state == c.CHOOSE:
|
if self.state == c.CHOOSE:
|
||||||
@ -86,6 +106,7 @@ class Level(tool.State):
|
|||||||
self.map.setMapGridType(x, y, c.MAP_EXIST)
|
self.map.setMapGridType(x, y, c.MAP_EXIST)
|
||||||
|
|
||||||
def initState(self):
|
def initState(self):
|
||||||
|
# 小游戏才有CHOOSEBAR_TYPE
|
||||||
if c.CHOOSEBAR_TYPE in self.map_data:
|
if c.CHOOSEBAR_TYPE in self.map_data:
|
||||||
self.bar_type = self.map_data[c.CHOOSEBAR_TYPE]
|
self.bar_type = self.map_data[c.CHOOSEBAR_TYPE]
|
||||||
else:
|
else:
|
||||||
@ -115,7 +136,11 @@ class Level(tool.State):
|
|||||||
self.menubar = menubar.MenuBar(card_list, self.map_data[c.INIT_SUN_NAME])
|
self.menubar = menubar.MenuBar(card_list, self.map_data[c.INIT_SUN_NAME])
|
||||||
else:
|
else:
|
||||||
self.menubar = menubar.MoveBar(card_list)
|
self.menubar = menubar.MoveBar(card_list)
|
||||||
|
|
||||||
|
# 是否拖住植物或者铲子
|
||||||
self.drag_plant = False
|
self.drag_plant = False
|
||||||
|
self.drag_shovel = False
|
||||||
|
|
||||||
self.hint_image = None
|
self.hint_image = None
|
||||||
self.hint_plant = False
|
self.hint_plant = False
|
||||||
if self.background_type == c.BACKGROUND_DAY and self.bar_type == c.CHOOSEBAR_STATIC:
|
if self.background_type == c.BACKGROUND_DAY and self.bar_type == c.CHOOSEBAR_STATIC:
|
||||||
@ -129,7 +154,121 @@ class Level(tool.State):
|
|||||||
self.setupZombies()
|
self.setupZombies()
|
||||||
self.setupCars()
|
self.setupCars()
|
||||||
|
|
||||||
|
# 地图有铲子才添加铲子
|
||||||
|
if self.hasShovel:
|
||||||
|
# 导入小铲子
|
||||||
|
frame_rect = [0, 0, 71, 67]
|
||||||
|
self.shovel = tool.get_image_menu(tool.GFX[c.SHOVEL], *frame_rect, c.BLACK, 1.1)
|
||||||
|
self.shovel_rect = self.shovel.get_rect()
|
||||||
|
frame_rect = [0, 0, 77, 75]
|
||||||
|
self.shovel_positon = (550, 2)
|
||||||
|
self.shovel_box = tool.get_image_menu(tool.GFX[c.SHOVEL_BOX], *frame_rect, c.BLACK, 1.1)
|
||||||
|
self.shovel_box_rect = self.shovel_box.get_rect()
|
||||||
|
self.shovel_rect.x = self.shovel_box_rect.x = self.shovel_positon[0]
|
||||||
|
self.shovel_rect.y = self.shovel_box_rect.y = self.shovel_positon[1]
|
||||||
|
|
||||||
|
self.setupLittleMenu()
|
||||||
|
|
||||||
|
# 小菜单
|
||||||
|
def setupLittleMenu(self):
|
||||||
|
# 具体运行游戏必定有个小菜单, 导入菜单和选项
|
||||||
|
frame_rect = [0, 0, 108, 31]
|
||||||
|
self.little_menu = tool.get_image_menu(tool.GFX[c.LITTLE_MENU], *frame_rect, c.BLACK, 1.1)
|
||||||
|
self.little_menu_rect = self.little_menu.get_rect()
|
||||||
|
self.little_menu_rect.x = 650
|
||||||
|
self.little_menu_rect.y = 0
|
||||||
|
|
||||||
|
frame_rect = [0, 0, 500, 500]
|
||||||
|
self.big_menu = tool.get_image_menu(tool.GFX[c.BIG_MENU], *frame_rect, c.BLACK, 1.1)
|
||||||
|
self.big_menu_rect = self.big_menu.get_rect()
|
||||||
|
self.big_menu_rect.x = 150
|
||||||
|
self.big_menu_rect.y = 0
|
||||||
|
|
||||||
|
frame_rect = [0, 0, 342, 87]
|
||||||
|
self.return_button = tool.get_image_menu(tool.GFX[c.RETURN_BUTTON], *frame_rect, c.BLACK, 1.1)
|
||||||
|
self.return_button_rect = self.return_button.get_rect()
|
||||||
|
self.return_button_rect.x = 220
|
||||||
|
self.return_button_rect.y = 440
|
||||||
|
|
||||||
|
frame_rect = [0, 0, 207, 45]
|
||||||
|
self.restart_button = tool.get_image_menu(tool.GFX[c.RESTART_BUTTON], *frame_rect, c.BLACK, 1.1)
|
||||||
|
self.restart_button_rect = self.restart_button.get_rect()
|
||||||
|
self.restart_button_rect.x = 295
|
||||||
|
self.restart_button_rect.y = 325
|
||||||
|
|
||||||
|
frame_rect = [0, 0, 206, 43]
|
||||||
|
self.mainMenu_button = tool.get_image_menu(tool.GFX[c.MAINMENU_BUTTON], *frame_rect, c.BLACK, 1.1)
|
||||||
|
self.mainMenu_button_rect = self.mainMenu_button.get_rect()
|
||||||
|
self.mainMenu_button_rect.x = 299
|
||||||
|
self.mainMenu_button_rect.y = 372
|
||||||
|
|
||||||
|
# 检查小菜单有没有被点击
|
||||||
|
def checkLittleMenuClick(self, mouse_pos):
|
||||||
|
x, y = mouse_pos
|
||||||
|
if(x >= self.little_menu_rect.x and x <= self.little_menu_rect.right and
|
||||||
|
y >= self.little_menu_rect.y and y <= self.little_menu_rect.bottom):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查小菜单的返回有没有被点击
|
||||||
|
def checkReturnClick(self, mouse_pos):
|
||||||
|
x, y = mouse_pos
|
||||||
|
if(x >= self.return_button_rect.x and x <= self.return_button_rect.right and
|
||||||
|
y >= self.return_button_rect.y and y <= self.return_button_rect.bottom):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查小菜单的重新开始有没有被点击
|
||||||
|
def checkRestartClick(self, mouse_pos):
|
||||||
|
x, y = mouse_pos
|
||||||
|
if(x >= self.restart_button_rect.x and x <= self.restart_button_rect.right and
|
||||||
|
y >= self.restart_button_rect.y and y <= self.restart_button_rect.bottom):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 检查小菜单的主菜单有没有被点击
|
||||||
|
def checkMainMenuClick(self, mouse_pos):
|
||||||
|
x, y = mouse_pos
|
||||||
|
if(x >= self.mainMenu_button_rect.x and x <= self.mainMenu_button_rect.right and
|
||||||
|
y >= self.mainMenu_button_rect.y and y <= self.mainMenu_button_rect.bottom):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
# 用小铲子移除植物
|
||||||
|
def shovelRemovePlant(self, mouse_pos):
|
||||||
|
x, y = mouse_pos
|
||||||
|
map_x, map_y = self.map.getMapIndex(x, y)
|
||||||
|
for i in self.plant_groups[map_y]:
|
||||||
|
if(x >= i.rect.x and x <= i.rect.right and
|
||||||
|
y >= i.rect.y and y <= i.rect.bottom):
|
||||||
|
i.kill()
|
||||||
|
return
|
||||||
|
|
||||||
|
# 检查小铲子的位置有没有被点击
|
||||||
|
# 方便放回去
|
||||||
|
def checkShovelClick(self, mouse_pos):
|
||||||
|
x, y = mouse_pos
|
||||||
|
if(x >= self.shovel_box_rect.x and x <= self.shovel_box_rect.right and
|
||||||
|
y >= self.shovel_box_rect.y and y <= self.shovel_box_rect.bottom):
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def play(self, mouse_pos, mouse_click):
|
def play(self, mouse_pos, mouse_click):
|
||||||
|
# 如果暂停
|
||||||
|
if self.showLittleMenu:
|
||||||
|
if mouse_click[0]:
|
||||||
|
if self.checkReturnClick(mouse_pos):
|
||||||
|
# 暂停 显示菜单
|
||||||
|
self.showLittleMenu = False
|
||||||
|
elif self.checkRestartClick(mouse_pos):
|
||||||
|
self.done = True
|
||||||
|
self.next = c.LEVEL
|
||||||
|
elif self.checkMainMenuClick(mouse_pos):
|
||||||
|
self.done = True
|
||||||
|
self.next = c.MAIN_MENU
|
||||||
|
self.persist = {c.CURRENT_TIME:0.0, c.LEVEL_NUM:c.START_LEVEL_NUM}
|
||||||
|
return
|
||||||
|
|
||||||
if self.zombie_start_time == 0:
|
if self.zombie_start_time == 0:
|
||||||
self.zombie_start_time = self.current_time
|
self.zombie_start_time = self.current_time
|
||||||
elif len(self.zombie_list) > 0:
|
elif len(self.zombie_list) > 0:
|
||||||
@ -150,6 +289,24 @@ class Level(tool.State):
|
|||||||
self.head_group.update(self.game_info)
|
self.head_group.update(self.game_info)
|
||||||
self.sun_group.update(self.game_info)
|
self.sun_group.update(self.game_info)
|
||||||
|
|
||||||
|
# wcb 添加
|
||||||
|
# 检查是否点击菜单
|
||||||
|
if mouse_click[0]:
|
||||||
|
if self.checkLittleMenuClick(mouse_pos):
|
||||||
|
# 暂停 显示菜单
|
||||||
|
self.showLittleMenu = True
|
||||||
|
elif self.checkShovelClick(mouse_pos):
|
||||||
|
self.drag_shovel = not self.drag_shovel
|
||||||
|
if self.drag_shovel:
|
||||||
|
# 小铲子要隐藏鼠标
|
||||||
|
pg.mouse.set_visible(False)
|
||||||
|
else:
|
||||||
|
self.removeMouseImagePlus()
|
||||||
|
elif self.drag_shovel:
|
||||||
|
# 移出这地方的植物
|
||||||
|
self.shovelRemovePlant(mouse_pos)
|
||||||
|
|
||||||
|
# 拖动植物或者铲子
|
||||||
if not self.drag_plant and mouse_pos and mouse_click[0]:
|
if not self.drag_plant and mouse_pos and mouse_click[0]:
|
||||||
result = self.menubar.checkCardClick(mouse_pos)
|
result = self.menubar.checkCardClick(mouse_pos)
|
||||||
if result:
|
if result:
|
||||||
@ -164,6 +321,10 @@ class Level(tool.State):
|
|||||||
self.addPlant()
|
self.addPlant()
|
||||||
elif mouse_pos is None:
|
elif mouse_pos is None:
|
||||||
self.setupHintImage()
|
self.setupHintImage()
|
||||||
|
elif self.drag_shovel:
|
||||||
|
if mouse_click[1]:
|
||||||
|
self.removeMouseImagePlus()
|
||||||
|
|
||||||
|
|
||||||
if self.produce_sun:
|
if self.produce_sun:
|
||||||
if(self.current_time - self.sun_timer) > c.PRODUCE_SUN_INTERVAL:
|
if(self.current_time - self.sun_timer) > c.PRODUCE_SUN_INTERVAL:
|
||||||
@ -171,7 +332,9 @@ class Level(tool.State):
|
|||||||
map_x, map_y = self.map.getRandomMapIndex()
|
map_x, map_y = self.map.getRandomMapIndex()
|
||||||
x, y = self.map.getMapGridPos(map_x, map_y)
|
x, y = self.map.getMapGridPos(map_x, map_y)
|
||||||
self.sun_group.add(plant.Sun(x, 0, x, y))
|
self.sun_group.add(plant.Sun(x, 0, x, y))
|
||||||
if not self.drag_plant and mouse_pos and mouse_click[0]:
|
|
||||||
|
# 检查有没有捡到阳光
|
||||||
|
if not self.drag_plant and not self.drag_shovel and mouse_pos and mouse_click[0]:
|
||||||
for sun in self.sun_group:
|
for sun in self.sun_group:
|
||||||
if sun.checkCollision(mouse_pos[0], mouse_pos[1]):
|
if sun.checkCollision(mouse_pos[0], mouse_pos[1]):
|
||||||
self.menubar.increaseSunValue(sun.sun_value)
|
self.menubar.increaseSunValue(sun.sun_value)
|
||||||
@ -181,6 +344,8 @@ class Level(tool.State):
|
|||||||
|
|
||||||
self.menubar.update(self.current_time)
|
self.menubar.update(self.current_time)
|
||||||
|
|
||||||
|
|
||||||
|
# 检查碰撞啥的
|
||||||
self.checkBulletCollisions()
|
self.checkBulletCollisions()
|
||||||
self.checkZombieCollisions()
|
self.checkZombieCollisions()
|
||||||
self.checkPlants()
|
self.checkPlants()
|
||||||
@ -204,6 +369,7 @@ class Level(tool.State):
|
|||||||
x, y = pg.mouse.get_pos()
|
x, y = pg.mouse.get_pos()
|
||||||
return self.map.showPlant(x, y)
|
return self.map.showPlant(x, y)
|
||||||
|
|
||||||
|
# 种植物
|
||||||
def addPlant(self):
|
def addPlant(self):
|
||||||
pos = self.canSeedPlant()
|
pos = self.canSeedPlant()
|
||||||
if pos is None:
|
if pos is None:
|
||||||
@ -317,6 +483,13 @@ class Level(tool.State):
|
|||||||
self.hint_image = None
|
self.hint_image = None
|
||||||
self.hint_plant = False
|
self.hint_plant = False
|
||||||
|
|
||||||
|
# 移除小铲子
|
||||||
|
def removeMouseImagePlus(self):
|
||||||
|
pg.mouse.set_visible(True)
|
||||||
|
self.drag_shovel = False
|
||||||
|
self.shovel_rect.x = self.shovel_positon[0]
|
||||||
|
self.shovel_rect.y = self.shovel_positon[1]
|
||||||
|
|
||||||
def checkBulletCollisions(self):
|
def checkBulletCollisions(self):
|
||||||
collided_func = pg.sprite.collide_circle_ratio(0.7)
|
collided_func = pg.sprite.collide_circle_ratio(0.7)
|
||||||
for i in range(self.map_y_len):
|
for i in range(self.map_y_len):
|
||||||
@ -524,6 +697,12 @@ class Level(tool.State):
|
|||||||
self.mouse_rect.centery = y
|
self.mouse_rect.centery = y
|
||||||
surface.blit(self.mouse_image, self.mouse_rect)
|
surface.blit(self.mouse_image, self.mouse_rect)
|
||||||
|
|
||||||
|
def drawMouseShowPlus(self, surface):
|
||||||
|
x, y = pg.mouse.get_pos()
|
||||||
|
self.shovel_rect.centerx = x
|
||||||
|
self.shovel_rect.centery = y
|
||||||
|
surface.blit(self.shovel, self.shovel_rect)
|
||||||
|
|
||||||
def drawZombieFreezeTrap(self, i, surface):
|
def drawZombieFreezeTrap(self, i, surface):
|
||||||
for zombie in self.zombie_groups[i]:
|
for zombie in self.zombie_groups[i]:
|
||||||
zombie.drawFreezeTrap(surface)
|
zombie.drawFreezeTrap(surface)
|
||||||
@ -534,6 +713,13 @@ class Level(tool.State):
|
|||||||
if self.state == c.CHOOSE:
|
if self.state == c.CHOOSE:
|
||||||
self.panel.draw(surface)
|
self.panel.draw(surface)
|
||||||
elif self.state == c.PLAY:
|
elif self.state == c.PLAY:
|
||||||
|
if self.hasShovel:
|
||||||
|
# 画铲子
|
||||||
|
surface.blit(self.shovel_box, self.shovel_box_rect)
|
||||||
|
surface.blit(self.shovel, self.shovel_rect)
|
||||||
|
# 画小菜单
|
||||||
|
surface.blit(self.little_menu, self.little_menu_rect)
|
||||||
|
|
||||||
self.menubar.draw(surface)
|
self.menubar.draw(surface)
|
||||||
for i in range(self.map_y_len):
|
for i in range(self.map_y_len):
|
||||||
self.plant_groups[i].draw(surface)
|
self.plant_groups[i].draw(surface)
|
||||||
@ -548,3 +734,12 @@ class Level(tool.State):
|
|||||||
|
|
||||||
if self.drag_plant:
|
if self.drag_plant:
|
||||||
self.drawMouseShow(surface)
|
self.drawMouseShow(surface)
|
||||||
|
|
||||||
|
if self.hasShovel and self.drag_shovel:
|
||||||
|
self.drawMouseShowPlus(surface)
|
||||||
|
|
||||||
|
if self.showLittleMenu:
|
||||||
|
surface.blit(self.big_menu, self.big_menu_rect)
|
||||||
|
surface.blit(self.return_button, self.return_button_rect)
|
||||||
|
surface.blit(self.restart_button, self.restart_button_rect)
|
||||||
|
surface.blit(self.mainMenu_button, self.mainMenu_button_rect)
|
||||||
@ -1,10 +1,11 @@
|
|||||||
__author__ = 'wszqkzqk'
|
__author__ = 'wszqkzqk'
|
||||||
|
|
||||||
import pygame as pg
|
import pygame as pg
|
||||||
from .. import tool
|
from .. import tool
|
||||||
from .. import constants as c
|
from .. import constants as c
|
||||||
|
from . import level
|
||||||
|
|
||||||
class Menu(tool.State):
|
class Menu(tool.State):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
tool.State.__init__(self)
|
tool.State.__init__(self)
|
||||||
|
|
||||||
@ -12,12 +13,15 @@ class Menu(tool.State):
|
|||||||
self.next = c.LEVEL
|
self.next = c.LEVEL
|
||||||
self.persist = persist
|
self.persist = persist
|
||||||
self.game_info = persist
|
self.game_info = persist
|
||||||
|
|
||||||
self.setupBackground()
|
self.setupBackground()
|
||||||
self.setupOption()
|
self.setupOption()
|
||||||
|
|
||||||
def setupBackground(self):
|
def setupBackground(self):
|
||||||
frame_rect = [80, 0, 800, 600]
|
frame_rect = [80, 0, 800, 600]
|
||||||
|
# 1、形参中加单星号,即f(*x)则表示x为元组,所有对x的操作都应将x视为元组类型进行。
|
||||||
|
# 2、双星号同上,区别是x视为字典。
|
||||||
|
# 3、在变量前加单星号表示将元组(列表、集合)拆分为单个元素。
|
||||||
|
# 4、双星号同上,区别是目标为字典,字典前加单星号的话可以得到“键”。
|
||||||
self.bg_image = tool.get_image(tool.GFX[c.MAIN_MENU_IMAGE], *frame_rect)
|
self.bg_image = tool.get_image(tool.GFX[c.MAIN_MENU_IMAGE], *frame_rect)
|
||||||
self.bg_rect = self.bg_image.get_rect()
|
self.bg_rect = self.bg_image.get_rect()
|
||||||
self.bg_rect.x = 0
|
self.bg_rect.x = 0
|
||||||
@ -29,14 +33,27 @@ class Menu(tool.State):
|
|||||||
frame_rect = [0, 0, 165, 77]
|
frame_rect = [0, 0, 165, 77]
|
||||||
|
|
||||||
for name in frame_names:
|
for name in frame_names:
|
||||||
self.option_frames.append(tool.get_image(tool.GFX[name], *frame_rect, c.BLACK, 1.7))
|
self.option_frames.append(tool.get_image_menu(tool.GFX[name], *frame_rect, c.BLACK, 1.7))
|
||||||
|
|
||||||
self.option_frame_index = 0
|
self.option_frame_index = 0
|
||||||
self.option_image = self.option_frames[self.option_frame_index]
|
self.option_image = self.option_frames[self.option_frame_index]
|
||||||
self.option_rect = self.option_image.get_rect()
|
self.option_rect = self.option_image.get_rect()
|
||||||
self.option_rect.x = 435
|
self.option_rect.x = 435
|
||||||
self.option_rect.y = 75
|
self.option_rect.y = 75
|
||||||
|
|
||||||
|
# 退出按钮
|
||||||
|
frame_rect = [0, 0, 500, 500]
|
||||||
|
self.option_exit = tool.get_image_menu(tool.GFX[c.EXIT], *frame_rect, c.BLACK, 1.1)
|
||||||
|
self.exit_rect = self.option_exit.get_rect()
|
||||||
|
self.exit_rect.x = 690
|
||||||
|
self.exit_rect.y = 400
|
||||||
|
|
||||||
|
# 小游戏
|
||||||
|
frame_rect = [0, 0, 317, 139]
|
||||||
|
self.option_littleGame = tool.get_image_menu(tool.GFX[c.LITTLEGAME_BUTTON], *frame_rect, c.BLACK, 0.9)
|
||||||
|
self.option_littleGame_rect = self.option_littleGame.get_rect()
|
||||||
|
self.option_littleGame_rect.x = 425
|
||||||
|
self.option_littleGame_rect.y = 200
|
||||||
|
|
||||||
self.option_start = 0
|
self.option_start = 0
|
||||||
self.option_timer = 0
|
self.option_timer = 0
|
||||||
self.option_clicked = False
|
self.option_clicked = False
|
||||||
@ -49,13 +66,34 @@ class Menu(tool.State):
|
|||||||
self.option_timer = self.option_start = self.current_time
|
self.option_timer = self.option_start = self.current_time
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
# 点击到按钮,修改转态的done属性
|
||||||
|
def checkExitClick(self, mouse_pos):
|
||||||
|
x, y = mouse_pos
|
||||||
|
if(x >= self.exit_rect.x and x <= self.exit_rect.right and
|
||||||
|
y >= self.exit_rect.y and y <= self.exit_rect.bottom):
|
||||||
|
self.done = True
|
||||||
|
self.next = c.EXIT
|
||||||
|
|
||||||
|
# 检查有没有按到小游戏
|
||||||
|
def checkLittleGameClick(self, mouse_pos):
|
||||||
|
x, y = mouse_pos
|
||||||
|
if(x >= self.option_littleGame_rect.x and x <= self.option_littleGame_rect.right and
|
||||||
|
y >= self.option_littleGame_rect.y and y <= self.option_littleGame_rect.bottom):
|
||||||
|
self.done = True
|
||||||
|
# 确实小游戏还是用的level
|
||||||
|
self.persist[c.LITTLEGAME_BUTTON] = True
|
||||||
|
|
||||||
def update(self, surface, current_time, mouse_pos, mouse_click):
|
def update(self, surface, current_time, mouse_pos, mouse_click):
|
||||||
self.current_time = self.game_info[c.CURRENT_TIME] = current_time
|
self.current_time = self.game_info[c.CURRENT_TIME] = current_time
|
||||||
|
|
||||||
|
# 没有选到选项时,检查有没有点到选项
|
||||||
if not self.option_clicked:
|
if not self.option_clicked:
|
||||||
if mouse_pos:
|
if mouse_pos:
|
||||||
self.checkOptionClick(mouse_pos)
|
self.checkOptionClick(mouse_pos)
|
||||||
|
self.checkExitClick(mouse_pos)
|
||||||
|
self.checkLittleGameClick(mouse_pos)
|
||||||
else:
|
else:
|
||||||
|
# 点到后播放动画
|
||||||
if(self.current_time - self.option_timer) > 200:
|
if(self.current_time - self.option_timer) > 200:
|
||||||
self.option_frame_index += 1
|
self.option_frame_index += 1
|
||||||
if self.option_frame_index >= 2:
|
if self.option_frame_index >= 2:
|
||||||
@ -65,5 +103,8 @@ class Menu(tool.State):
|
|||||||
if(self.current_time - self.option_start) > 1300:
|
if(self.current_time - self.option_start) > 1300:
|
||||||
self.done = True
|
self.done = True
|
||||||
|
|
||||||
|
|
||||||
surface.blit(self.bg_image, self.bg_rect)
|
surface.blit(self.bg_image, self.bg_rect)
|
||||||
surface.blit(self.option_image, self.option_rect)
|
surface.blit(self.option_image, self.option_rect)
|
||||||
|
surface.blit(self.option_exit, self.exit_rect)
|
||||||
|
surface.blit(self.option_littleGame, self.option_littleGame_rect)
|
||||||
@ -1,5 +1,4 @@
|
|||||||
__author__ = 'wszqkzqk'
|
__author__ = 'wszqkzqk'
|
||||||
|
|
||||||
import pygame as pg
|
import pygame as pg
|
||||||
from .. import tool
|
from .. import tool
|
||||||
from .. import constants as c
|
from .. import constants as c
|
||||||
|
|||||||
@ -1,37 +1,40 @@
|
|||||||
__author__ = 'wszqkzqk'
|
__author__ = 'wszqkzqk'
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import sys
|
import sys
|
||||||
from abc import abstractmethod
|
from abc import abstractmethod
|
||||||
import pygame as pg
|
import pygame as pg
|
||||||
|
from pygame.locals import *
|
||||||
from . import constants as c
|
from . import constants as c
|
||||||
|
|
||||||
|
# an abstract class, one state of automata
|
||||||
class State():
|
class State():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.start_time = 0.0
|
self.start_time = 0.0
|
||||||
self.current_time = 0.0
|
self.current_time = 0.0
|
||||||
self.done = False
|
self.done = False # false 代表未做完
|
||||||
self.next = None
|
self.next = None # 表示这个状态退出后要转到的下一个状态
|
||||||
self.persist = {}
|
self.persist = {} # 在状态间转换时需要传递的数据
|
||||||
|
|
||||||
|
# 当从其他状态进入这个状态时,需要进行的初始化操作
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def startup(self, current_time, persist):
|
def startup(self, current_time, persist):
|
||||||
'''abstract method'''
|
'''abstract method'''
|
||||||
|
# 当从这个状态退出时,需要进行的清除操作
|
||||||
def cleanup(self):
|
def cleanup(self):
|
||||||
self.done = False
|
self.done = False
|
||||||
return self.persist
|
return self.persist
|
||||||
|
# 在这个状态运行时进行的更新操作
|
||||||
@abstractmethod
|
@abstractmethod
|
||||||
def update(self, surface, keys, current_time):
|
def update(self, surface, keys, current_time):
|
||||||
'''abstract method'''
|
'''abstract method'''
|
||||||
|
|
||||||
|
# control this game. do event loops
|
||||||
class Control():
|
class Control():
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
self.screen = pg.display.get_surface()
|
self.screen = pg.display.get_surface()
|
||||||
self.done = False
|
self.done = False
|
||||||
self.clock = pg.time.Clock()
|
self.clock = pg.time.Clock() # 创建一个对象来帮助跟踪时间
|
||||||
self.fps = 60
|
self.fps = 60
|
||||||
self.keys = pg.key.get_pressed()
|
self.keys = pg.key.get_pressed()
|
||||||
self.mouse_pos = None
|
self.mouse_pos = None
|
||||||
@ -50,15 +53,22 @@ class Control():
|
|||||||
self.state.startup(self.current_time, self.game_info)
|
self.state.startup(self.current_time, self.game_info)
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
|
# 返回自 pygame_init() 调用以来的毫秒数
|
||||||
self.current_time = pg.time.get_ticks()
|
self.current_time = pg.time.get_ticks()
|
||||||
|
|
||||||
if self.state.done:
|
if self.state.done:
|
||||||
self.flip_state()
|
self.flip_state()
|
||||||
|
|
||||||
self.state.update(self.screen, self.current_time, self.mouse_pos, self.mouse_click)
|
self.state.update(self.screen, self.current_time, self.mouse_pos, self.mouse_click)
|
||||||
self.mouse_pos = None
|
self.mouse_pos = None
|
||||||
self.mouse_click[0] = False
|
self.mouse_click[0] = False
|
||||||
self.mouse_click[1] = False
|
self.mouse_click[1] = False
|
||||||
|
|
||||||
|
# 状态转移
|
||||||
def flip_state(self):
|
def flip_state(self):
|
||||||
|
if self.state.next == c.EXIT:
|
||||||
|
pg.quit()
|
||||||
|
os._exit(0)
|
||||||
previous, self.state_name = self.state_name, self.state.next
|
previous, self.state_name = self.state_name, self.state.next
|
||||||
persist = self.state.cleanup()
|
persist = self.state.cleanup()
|
||||||
self.state = self.state_dict[self.state_name]
|
self.state = self.state_dict[self.state_name]
|
||||||
@ -76,8 +86,11 @@ class Control():
|
|||||||
self.mouse_pos = pg.mouse.get_pos()
|
self.mouse_pos = pg.mouse.get_pos()
|
||||||
self.mouse_click[0], _, self.mouse_click[1] = pg.mouse.get_pressed()
|
self.mouse_click[0], _, self.mouse_click[1] = pg.mouse.get_pressed()
|
||||||
print('pos:', self.mouse_pos, ' mouse:', self.mouse_click)
|
print('pos:', self.mouse_pos, ' mouse:', self.mouse_click)
|
||||||
|
#else:
|
||||||
|
# print(pg.event.event_name(event.type))
|
||||||
|
|
||||||
def main(self):
|
|
||||||
|
def run(self):
|
||||||
while not self.done:
|
while not self.done:
|
||||||
self.event_loop()
|
self.event_loop()
|
||||||
self.update()
|
self.update()
|
||||||
@ -89,6 +102,19 @@ def get_image(sheet, x, y, width, height, colorkey=c.BLACK, scale=1):
|
|||||||
image = pg.Surface([width, height])
|
image = pg.Surface([width, height])
|
||||||
rect = image.get_rect()
|
rect = image.get_rect()
|
||||||
|
|
||||||
|
image.blit(sheet, (0, 0), (x, y, width, height))
|
||||||
|
if colorkey != c.NULL:
|
||||||
|
image.set_colorkey(colorkey)
|
||||||
|
image = pg.transform.scale(image,
|
||||||
|
(int(rect.width*scale),
|
||||||
|
int(rect.height*scale)))
|
||||||
|
return image
|
||||||
|
|
||||||
|
def get_image_menu(sheet, x, y, width, height, colorkey=c.BLACK, scale=1):
|
||||||
|
# 一定要保留阿尔法通道,修复主菜单bug,游戏中car显示又有bug
|
||||||
|
image = pg.Surface([width, height], SRCALPHA)
|
||||||
|
rect = image.get_rect()
|
||||||
|
|
||||||
image.blit(sheet, (0, 0), (x, y, width, height))
|
image.blit(sheet, (0, 0), (x, y, width, height))
|
||||||
image.set_colorkey(colorkey)
|
image.set_colorkey(colorkey)
|
||||||
image = pg.transform.scale(image,
|
image = pg.transform.scale(image,
|
||||||
@ -101,7 +127,7 @@ def load_image_frames(directory, image_name, colorkey, accept):
|
|||||||
tmp = {}
|
tmp = {}
|
||||||
# image_name is "Peashooter", pic name is 'Peashooter_1', get the index 1
|
# image_name is "Peashooter", pic name is 'Peashooter_1', get the index 1
|
||||||
index_start = len(image_name) + 1
|
index_start = len(image_name) + 1
|
||||||
frame_num = 0;
|
frame_num = 0
|
||||||
for pic in os.listdir(directory):
|
for pic in os.listdir(directory):
|
||||||
name, ext = os.path.splitext(pic)
|
name, ext = os.path.splitext(pic)
|
||||||
if ext.lower() in accept:
|
if ext.lower() in accept:
|
||||||
@ -119,6 +145,7 @@ def load_image_frames(directory, image_name, colorkey, accept):
|
|||||||
frame_list.append(tmp[i])
|
frame_list.append(tmp[i])
|
||||||
return frame_list
|
return frame_list
|
||||||
|
|
||||||
|
# colorkeys 是设置图像中的某个颜色值为透明,这里用来消除白边
|
||||||
def load_all_gfx(directory, colorkey=c.WHITE, accept=('.png', '.jpg', '.bmp', '.gif')):
|
def load_all_gfx(directory, colorkey=c.WHITE, accept=('.png', '.jpg', '.bmp', '.gif')):
|
||||||
graphics = {}
|
graphics = {}
|
||||||
for name1 in os.listdir(directory):
|
for name1 in os.listdir(directory):
|
||||||
@ -154,23 +181,24 @@ def load_all_gfx(directory, colorkey=c.WHITE, accept=('.png', '.jpg', '.bmp', '.
|
|||||||
graphics[name] = img
|
graphics[name] = img
|
||||||
return graphics
|
return graphics
|
||||||
|
|
||||||
|
# 从文件加载矩形碰撞范围
|
||||||
def loadZombieImageRect():
|
def loadZombieImageRect():
|
||||||
file_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'source', 'data', 'entity', 'zombie.json')
|
file_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'resources', 'data', 'entity', 'zombie.json')
|
||||||
f = open(file_path)
|
f = open(file_path)
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
return data[c.ZOMBIE_IMAGE_RECT]
|
return data[c.ZOMBIE_IMAGE_RECT]
|
||||||
|
|
||||||
def loadPlantImageRect():
|
def loadPlantImageRect():
|
||||||
file_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'source', 'data', 'entity', 'plant.json')
|
file_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'resources', 'data', 'entity', 'plant.json')
|
||||||
f = open(file_path)
|
f = open(file_path)
|
||||||
data = json.load(f)
|
data = json.load(f)
|
||||||
f.close()
|
f.close()
|
||||||
return data[c.PLANT_IMAGE_RECT]
|
return data[c.PLANT_IMAGE_RECT]
|
||||||
|
|
||||||
pg.init()
|
pg.init()
|
||||||
pg.display.set_caption(c.ORIGINAL_CAPTION)
|
pg.display.set_caption(c.ORIGINAL_CAPTION) # 设置标题
|
||||||
SCREEN = pg.display.set_mode(c.SCREEN_SIZE)
|
SCREEN = pg.display.set_mode(c.SCREEN_SIZE) # 设置初始屏幕
|
||||||
|
|
||||||
GFX = load_all_gfx(os.path.join(os.path.dirname(os.path.dirname(__file__)) ,os.path.join("resources","graphics")))
|
GFX = load_all_gfx(os.path.join(os.path.dirname(os.path.dirname(__file__)) ,os.path.join("resources","graphics")))
|
||||||
ZOMBIE_RECT = loadZombieImageRect()
|
ZOMBIE_RECT = loadZombieImageRect()
|
||||||
|
|||||||