下面是我正在研究的一个小Kivy应用程序。目前我正在尝试实施基本的重置功能。基本上,如果敌人与玩家发生碰撞,我希望游戏重置。游戏结束时,在与敌人发生碰撞时取消时间安排。之后我想我可以在之后调用main(),但这只会导致游戏中左右错误的大量错误。我还尝试在unhedule之后添加了重新安排规则,但这只是覆盖了unhedule并保持游戏继续。
注意:游戏主要是从游戏类到代码底部处理。它也是您可以查看时钟安排规则的地方。
import kivy
kivy.require('1.1.1')
from kivy.app import App
from kivy.uix.widget import Widget
from kivy.properties import ObjectProperty, ListProperty, NumericProperty, BooleanProperty
from kivy.core.audio import SoundLoader
import math
from kivy.clock import Clock
import time
import random
sound = SoundLoader.load('gamemusic.mp3')
PLAYER_SPEED = 10
ENEMY_SPEED = 4
ENEMY_SPAWN = 5
UPDATE_SPEED = .01
MIN_INITIAL_PLAYER_MINION_DISTANCE = 200
UPDATE_SCORE = 1
MAX_DECOYS = 3
if sound:
sound.loop = True
sound.play()
class Movable(Widget):
velocity_x = NumericProperty(0)
velocity_y = NumericProperty(0)
target = ListProperty([])
def move(self):
dx = self.target[0] - self.center[0]
dy = self.target[1] - self.center[1]
total = math.sqrt(dx**2 + dy**2)
if total >0:
self.velocity_x = (dx / total) * self.speed
self.velocity_y = (dy / total) * self.speed
new_x = self.pos[0] + self.velocity_x
new_y = self.pos[1] + self.velocity_y
self.pos = (new_x,new_y)
elif total <=0:
self.velocity_x = self.speed
self.velocity_y = self.speed
class Player(Movable):
target = ListProperty([])
def __init__(self, **kwargs):
Widget.__init__(self)
self.target = [399.0, 399.0]
self.speed = PLAYER_SPEED
def update_target(self, new_target):
self.target = new_target
if distance_pos(self.center, self.target) <= self.speed*2:
self.target = self.center
class Enemy(Movable):
randomColor = random.randint(0,1)
alert = BooleanProperty(False)
def __init__(self, **kwargs):
Widget.__init__(self)
self.world_width = kwargs.get("width",0)
self.world_height = kwargs.get("height",0)
self.speed = ENEMY_SPEED
x_target = float(random.randint(0, self.world_width))
y_target = float(random.randint(0, self.world_height))
self.target = [x_target, y_target]
self.center = kwargs.get('start_pos',[0,0])
def update_target(self, player, enemies, decoys):
alert_list = self.alerted(enemies)
if len(decoys) > 0:
self.target = decoys[0].center
self.alert = False
elif distance(player, self) < 150:
self.alert = True
self.target = player.center
elif len(alert_list) > 0:
self.target = alert_list[0].center
self.alert = False
else:
if distance_pos(self.center, self.target) <= self.speed*2:
x_new_target = float(random.randint(0, self.world_width))
y_new_target = float(random.randint(0, self.world_height))
self.target = [x_new_target, y_new_target]
def alerted(self, enemies):
alert_list = []
for item in enemies:
if item.alert == True and distance(self, item) < 150:
alert_list.append(item)
return alert_list
class Decoy(Widget):
def __init__(self, **kwargs):
Widget.__init__(self)
self.center = kwargs.get('start_pos',[0,0])
pass
def distance(widget1, widget2):
return distance_pos(widget1.center, widget2.center)
def distance_pos(pos1, pos2):
dist = math.sqrt((pos1[0]-pos2[0])**2 + (pos1[1]-pos2[1])**2)
return dist
class Game(Widget):
player1 = ObjectProperty(None)
enemies = ListProperty([])
decoys = ListProperty([])
score = NumericProperty()
def setup(self):
self.enemies = []
self.decoys = []
self.player1.center = self.center
self.setup_schedules()
#Don't forget about good code organization!
def setup_schedules(self):
Clock.schedule_interval(self.update, UPDATE_SPEED)
Clock.schedule_interval(self.spawn_enemy, ENEMY_SPAWN)
Clock.schedule_interval(self.increase_score, UPDATE_SCORE)
def update(self,dt):
self.player1.move()
for item in self.enemies:
item.update_target(self.player1,self.enemies,self.decoys)
item.move()
if self.player1.collide_widget(item):
Clock.unschedule(self.spawn_enemy)
Clock.unschedule(self.update)
Clock.unschedule(self.increase_score)
"""
def death_restart(self, player):
if self.collide_widget(player):
print("error")
#main()
"""
def spawn_enemy(self, dt):
if len(self.enemies) <= 8:
x = float(random.randint(0, self.width))
y = float(random.randint(0, self.height))
enemy = Enemy(start_pos = (x,y),width = self.width,height = self.height)
while distance(enemy, self.player1)< MIN_INITIAL_PLAYER_MINION_DISTANCE:
x = float(random.randint(0, self.width))
y = float(random.randint(0, self.height))
enemy.pos = (x,y)
self.enemies.append(enemy)
self.add_widget(enemy)
def spawn_decoy(self, location):
x = location[0]
y = location[1]
decoy = Decoy(start_pos = (x,y))
self.decoys.append(decoy)
self.add_widget(decoy)
def increase_score(self, dt):
self.score += 1
#on_touch_move vs on_touch_down
def on_touch_move(self, touch):
self.player1.update_target([touch.x, touch.y])
def on_touch_down(self, touch):
if touch.is_double_tap and len(self.decoys) < MAX_DECOYS:
self.spawn_decoy([touch.x, touch.y])
#Entry Point into app
class GameApp(App):
def build(self):
game = Game()
game.setup()
return game
def main():
GameApp().run()
main()