Я создаю Space Invaders, но он не работает так, как должен
Для моего класса программирования я работаю над игрой Space Invaders... Мой код не идеален, но в основном он работает. В основном...
Я не буду вдаваться в подробности (я добавлю ссылку на страницу Codeskulptor, чтобы вы могли убедиться в этом сами), но меня беспокоит лишь то, что мои враги замедляются, где они должны ускориться!
Я печатаю горизонтальную скорость (VX) на консоли, и я вижу, что она увеличивается. Ускорение работает должным образом до определенной точки, где они просто снова замедляются, а vx все еще увеличивается?! Это действительно легко заметить, когда осталось только четверо врагов...
Все вражеские / инопланетные объекты хранятся в списке, когда они попадают под лазерный луч, они удаляются из списка с помощью функции 'kill'.
Вот функция:
def kill(enemy):
global points
points += 1
for enemies in EnemyList_1:
if enemies.vx > 0:
enemies.vx += 1.0/4/60
elif enemies.vx < 0:
enemies.vx -= 1.0/4/60
EnemyList_1.remove(enemy)
Как вы можете видеть вражеские объекты в списке EnemyList_1, и они удаляются при вызове функции (функция вызывается следующей функцией в моем классе врагов):
def laserhit(self, laser):
global wait, FriendLaserList
if abs(self.x - laser.x) < self.size[0] / 2.0 and abs(self.y - laser.y) < self.size[1] / 2.0:
laser.x = WIDTH
laser.y = HEIGHT
laser.pos = [WIDTH, HEIGHT]
laser.vy = 0
wait = 0.0
FriendLaserList = []
kill(self)
Переменная ожидания - это то, что я вставил для создания перезарядки между лазерным включением. Не беспокойтесь, глядя на это
Мой код, вероятно, выглядит как крушение поезда, но по большей части он работает, и я доволен своей собственной работой, это первый раз, когда я сделал что-то подобное...
Ссылка на игру (конечно, не заканчивается, также все комментарии на голландском, для моего учителя и т. Д., Но все переменные на английском языке: http://www.codeskulptor.org/
Первые пару раз вы пытаетесь запустить его, он не будет работать, потому что модуль SimpleGui загружает изображения. (Наш учитель принимает только изображения, хранящиеся в Google Диске)
Мой животрепещущий вопрос: почему мои враги замедляются, когда со временем их убивают, а в моем коде прямо говорится, что они должны ускориться?
PS: я пытался вместо того, чтобы удалить врагов из списка, просто поместить их за пределы холста, но это доставило мне проблемы с проверкой столкновения лазера и врага. Я бы предпочел просто удалить их, так как это делает игру более гладкой. Я также пробовал.pop() и 'del', но у меня та же проблема
Я прошу прощения за мой код n00b и мои ошибки на английском...
Нет, но серьезно, не волнуйтесь из-за того, насколько плох мой код прямо сейчас, многие вещи не работали, и мне пришлось быстро менять значения и т. Д., Но как только все заработало как надо, я его почистил и т. Д. Правильно теперь мне просто нужно это исправить, и я так растерялся, что-то, что я сделал, или это просто ошибка...
Весь мой код для людей, которые не хотят идти на CodeSulptor (Внимание: это беспорядок!):
import simplegui
import random
# Frame opties
WIDTH = 450.0
HEIGHT = 600.0
BORDER = (WIDTH / 16, HEIGHT / 12, 1, 'white')
# Vijand opties
# Grootte van de vijanden kan je aanpassen, ook het aantal.
# Aantal/Grootte. Natuurlijk niet te groot maken...
enemy_size = 20.0
enemy_centrepoint = enemy_size / 2.0
enemy_rows = 3
enemy_row_amount = 13
enemy_amount = enemy_row_amount * enemy_rows
# Score
level = 1
points = 0
# Speler
lives = 3
player_size = 22.0
# Plaatjes
heart = simplegui.load_image('http://googledrive.com/host/0BzEhWaGeU4yUVEFJazFnVDJiRFE/hart.png')
heartwh = [heart.get_width(), heart.get_height()]
heartcenter = [heartwh[0] / 2, heartwh[1] / 2]
# Overige variabelen.
PADDING = (BORDER[0] + enemy_size * 4.0, BORDER[1] + enemy_size * 0.64285714285)
SPACING = (WIDTH - PADDING[0] * 2.0) / (enemy_row_amount - 1)
CheckX = PADDING[0] - BORDER[0] - enemy_centrepoint
# Class voor de vijanden van level 1
class Enemy_One(object):
image = simplegui.load_image('http://googledrive.com/host/0BzEhWaGeU4yUVEFJazFnVDJiRFE/vijand1wit.png')
width = image.get_width()
height = image.get_height()
wh = (width, height)
center = (width / 2.0, height / 2.0)
size = (enemy_size,enemy_size * height/width)
vx = enemy_size/20.0/60.0
vy = enemy_size / 2.0
att = 2000
def __init__(self, x, y):
self.x = x
self.y = y
self.pos = [float(self.x),float(self.y)]
self.x_org = self.pos[0]
# Verandert positie vijanden
def update(self):
self.x = self.pos[0]
self.y = self.pos[1]
# Bepaalt of de vijanden schieten of niet.
def shoot(self):
self.attack = random.randrange(0,int(self.att))
if 6 <= self.attack <= 7:
EnemyLaserList.append(EnemyLaser(self.pos[0], self.pos[1]))
# Bepaalt of de vijanden worden geraakt of niet
def laserhit(self, laser):
global wait, FriendLaserList
if abs(self.x - laser.x) < self.size[0] / 2.0 and abs(self.y - laser.y) < self.size[1] / 2.0:
laser.x = WIDTH
laser.y = HEIGHT
laser.pos = [WIDTH, HEIGHT]
laser.vy = 0
wait = 0.0
FriendLaserList = []
kill(self)
# Class voor de Fighter (jij)
class Fighter(object):
image = simplegui.load_image('http://googledrive.com/host/0BzEhWaGeU4yUVEFJazFnVDJiRFE/speler.png')
width = image.get_width()
height = image.get_height()
wh = (width, height)
center = (width / 2.0, height / 2.0)
vx = 0
vx_org = 5
size = (player_size, player_size * height/width)
def __init__(self, x, y):
self.x = x
self.y = y
self.pos = [self.x, self.y]
def move(self):
if BORDER[0] + player_size / 2.0 < self.x < WIDTH - BORDER[0] - player_size / 2.0:
self.x += self.vx
self.pos = [self.x, self.y]
elif self.x <= BORDER[0] + player_size / 2.0:
self.x += 1
elif self.x >= WIDTH - BORDER[0] - player_size / 2.0:
self.x -= 1
# Kijken of de speler wordt geraakt door een laser
def laserhit(self, laser):
global lives
if abs(self.x - laser.x) < self.size[0] / 2.0 and abs(self.y - laser.y) < self.size[1] / 2.0:
lives -= 1
elaserkill(laser)
# Schieten
def shoot(self):
global FriendLaserList
FriendLaserList.append(FriendlyLaser(self.x, self.y))
FriendLaserList = []
# Class voor de laser van de speler
class FriendlyLaser(object):
image = simplegui.load_image('http://googledrive.com/host/0BzEhWaGeU4yUVEFJazFnVDJiRFE/lasergroen.png')
width = image.get_width()
height = image.get_height()
wh = (width, height)
center = (width / 2, height / 2)
vy = -10
size = (enemy_size / 10.0, enemy_size * 4 / 10.0)
def __init__(self,x,y):
self.x = x
self.y = y
self.pos = [self.x, self.y]
# Verandert positie vriendelijke laser.
def update(self):
self.y += self.vy
self.pos = [self.x, self.y]
if self.y < BORDER[1] or self.pos == [WIDTH, HEIGHT]:
flaserkill(self)
# Class voor de vijand lasers
class EnemyLaser(object):
image = simplegui.load_image('http://googledrive.com/host/0BzEhWaGeU4yUVEFJazFnVDJiRFE/laser.png')
width = image.get_width()
height = image.get_height()
wh = (width, height)
center = (width / 2, height / 2)
vy = 5
size = (enemy_size / 10.0, enemy_size * 4 / 10.0)
def __init__(self,x,y):
self.x = x
self.y = y
self.pos = [self.x, self.y]
# Verandert positie vijandelijke laser.
def update(self):
self.y += self.vy
self.pos = [self.x, self.y]
if self.y > HEIGHT - 10 or self.pos == [WIDTH, HEIGHT]:
elaserkill(self)
# Speler
player = Fighter(WIDTH / 2.0, (HEIGHT - BORDER[1]) + (BORDER[1] / 2.0))
# Vijand Laser list
EnemyLaserList = []
# Level 1 vijanden maken
EnemyList_1 = []
def level_1():
global EnemyList_1, lives, points, EnemyLaserList, level, FriendLaserList, wait
wait = 0.0
level = 1
lives = 3
points = 0
EnemyList_1 = []
EnemyLaserList = []
FriendLaserList = []
for i in range(0,enemy_amount + 1):
# Rij 1
if i < enemy_row_amount:
EnemyList_1.append(Enemy_One(PADDING[0] + SPACING * (i),PADDING[1]))
# Rij 2
elif enemy_row_amount < i <= enemy_row_amount * 2:
EnemyList_1.append(Enemy_One(PADDING[0] + SPACING * (i-enemy_row_amount - 1),PADDING[1] + SPACING))
# Rij 3
elif i > enemy_row_amount * 2:
EnemyList_1.append(Enemy_One(PADDING[0] + SPACING * (i-enemy_row_amount * 2 - 1),PADDING[1] + SPACING * 2))
# Vijanden positie verplaatsen
def posupdate():
global lives
for enemy in EnemyList_1:
if enemy.x_org - CheckX <= enemy.pos[0] <= enemy.x_org + CheckX:
enemy.pos[0] += enemy.vx
elif enemy.y + enemy.wh[1] >= HEIGHT - BORDER[1]:
lives = 0
else:
enemy.vx = -enemy.vx
enemy.pos[0] += enemy.vx
enemy.pos[1] += enemy.vy
# Haal vijanden weg
def kill(enemy):
global points
points += 1
for enemies in EnemyList_1:
if enemies.vx > 0:
enemies.vx += 1.0/4/60
elif enemies.vx < 0:
enemies.vx -= 1.0/4/60
if enemies.att > 2000 * 0.95 ** 10:
enemies.att = enemy.att * 0.95
elif enemies.att < 2000 * 0.95 ** 10:
enemies.att = enemy.att * 0.97
EnemyList_1.remove(enemy)
print len(EnemyList_1)
def elaserkill(laser):
EnemyLaserList.remove(laser)
def flaserkill(laser):
FriendLaserList.remove(laser)
def draw(canvas):
global level, points, lives, wait
# Tekst, score, levens, etc.
canvas.draw_text('LEVENS: ',(BORDER[0] + 10, 20),20, 'white', 'monospace')
canvas.draw_text('SCORE: ' + str(points),(BORDER[0] + 10, 20 * 2),20, 'white', 'monospace')
canvas.draw_text('LEVEL: ' + str(level),(WIDTH - BORDER[0] - frame.get_canvas_textwidth('LEVEL: ' + str(level),20,'monospace'), 20 * 2),20, 'white', 'monospace')
for i in range(1, lives + 1):
canvas.draw_image(heart,
heartcenter,
heartwh,
[BORDER[0] + 10 + text_levens + 20 * i,
13],
(20,
20.0 * heartwh[1]/heartwh[0]))
# Borders voor debuggen
canvas.draw_line((BORDER[0],0),
(BORDER[0],HEIGHT),
BORDER[2],
BORDER[3]
)
canvas.draw_line((WIDTH-BORDER[0],0),
(WIDTH-BORDER[0],HEIGHT),
BORDER[2],
BORDER[3]
)
canvas.draw_line((0,BORDER[1]),
(WIDTH,BORDER[1]),
BORDER[2],
BORDER[3]
)
canvas.draw_line((0,HEIGHT - BORDER[1]),
(WIDTH,HEIGHT - BORDER[1]),
BORDER[2],
BORDER[3]
)
# Teken vijandelijke lasers
for laser in EnemyLaserList:
laser.update()
canvas.draw_image(laser.image,
laser.center,
laser.wh,
laser.pos,
laser.size)
if points == enemy_amount and level == 1:
#level = 2
#levellabel.set_text("Level 2")
if lives < 4:
lives += 1
canvas.draw_text("Je hebt gewonnen!",
(WIDTH / 2 - frame.get_canvas_textwidth('Je hebt gewonnen!', 40, 'monospace') / 2,HEIGHT / 2),
40, 'white', 'monospace')
canvas.draw_text("Druk op 'R' voor een replay!",
(WIDTH / 2 - 10 - frame.get_canvas_textwidth('Druk op 'R' voor een replay!', 20, 'monospace') / 2,HEIGHT / 2 + HEIGHT / 8),
20, 'white', 'monospace')
if lives <= 0:
canvas.draw_text("Je hebt verloren!",
(WIDTH / 2 - frame.get_canvas_textwidth('Je hebt verloren!', 40, 'monospace') / 2,HEIGHT / 2),
40, 'white', 'monospace')
canvas.draw_text("Druk op 'R' voor een replay!",
(WIDTH / 2 - 10 - frame.get_canvas_textwidth('Druk op 'R' voor een replay!', 20, 'monospace') / 2,HEIGHT / 2 + HEIGHT / 8),
20, 'white', 'monospace')
else:
# Teken & beweeg speler
player.move()
canvas.draw_image(player.image,
player.center,
player.wh,
player.pos,
player.size)
# Laser hit checken voor de speler
for laser in EnemyLaserList:
player.laserhit(laser)
# Schieten check
if wait > 0.0:
wait -= 1/60.0
else:
wait = 0.0
# Laser v.d. speler tekenen
for laser in FriendLaserList:
laser.update()
canvas.draw_image(laser.image,
laser.center,
laser.wh,
laser.pos,
laser.size)
# Level 1 vijanden
if level == 1:
# Update posities
for enemy in EnemyList_1:
posupdate()
enemy.update()
enemy.shoot()
for laser in FriendLaserList:
enemy.laserhit(laser)
# Teken vijanden
for enemy in EnemyList_1:
canvas.draw_image(enemy.image,
enemy.center,
enemy.wh,
enemy.pos,
enemy.size)
# Debug Labels
pointslabel.set_text("Punten: " + str(points))
liveslabel.set_text("Levens: " + str(lives))
# Debug vermoorden van vijanden
# Ze worden sneller naarmate er meer doodgaan.
# Ze gaan meer aanvallen naarmate er meer doodgaan.
indexlist = []
wait = 0.0
def keydown(key):
global wait
# Speler bewegen naar links
if key == simplegui.KEY_MAP['left']:
player.vx = -player.vx_org
# Speler bewegen naar rechts
elif key == simplegui.KEY_MAP['right']:
player.vx = player.vx_org
# Spel opnieuw spelen
elif key == simplegui.KEY_MAP['r']:
level_1()
# Schieten
elif key == simplegui.KEY_MAP['space']:
if wait == 0.0:
wait = 1.0
player.shoot()
def keyup(key):
if key == simplegui.KEY_MAP['left']:
player.vx = 0
elif key == simplegui.KEY_MAP['right']:
player.vx = 0
def button_kill():
global points, indexlist
# 'Dood' vijand, voor testen!
kill(EnemyList_1[0])
def button_lives_add():
global lives
lives += 1
def button_lives_del():
global lives
lives -= 1
# Frame maken
frame = simplegui.create_frame("Game",WIDTH,HEIGHT)
frame.set_draw_handler(draw)
frame.set_keyup_handler(keyup)
frame.set_keydown_handler(keydown)
text_levens = frame.get_canvas_textwidth('LEVENS:', 20, 'monospace')
# Debug buttons.
debuglabel = frame.add_label("Debug knoppen.")
button = frame.add_button("Random Kill Enemy",button_kill,150)
pointslabel = frame.add_label("")
liveslabel = frame.add_label("")
levellabel = frame.add_label("Level: " + str(level))
button2 = frame.add_button("Extra leven",button_lives_add,150)
button2 = frame.add_button("Een leven minder",button_lives_del,150)
# Starten (level 1 & frame)
level_1()
frame.start()
Если вам нужны более конкретные части моего кода, пожалуйста, спросите. Я слышал, что людям не нравится, когда им приходится читать весь код...
2 ответа
Я думаю, что это связано с производительностью. Когда у вас есть куча врагов, их отнимает больше времени. Я не знаю, как simplegui справляется с этим, но похоже, что вы ожидаете, что он будет давать вам кадр 60 раз в секунду, что может быть неверным предположением.
Я починил это! Я взял функцию posupdate() из своего кода и переписал ее в классе обновлений у своих врагов. Я не знаю, что на самом деле происходит, но это исправлено, и игра даже работает намного лучше.
Что я сделал: я превратил posupdate() в update(self) в классе Enemy_One
def posupdate():
global lives
for enemy in EnemyList_1:
if enemy.x_org - CheckX <= enemy.pos[0] <= enemy.x_org + CheckX:
enemy.pos[0] += enemy.vx
elif enemy.y + enemy.wh[1] >= HEIGHT - BORDER[1]:
lives = 0
else:
enemy.vx = -enemy.vx
enemy.pos[0] += enemy.vx
enemy.pos[1] += enemy.vy
Все работает сейчас!
class Enemy_One(object):
image = simplegui.load_image('http://googledrive.com/host/0BzEhWaGeU4yUVEFJazFnVDJiRFE/vijand1wit.png')
width = image.get_width()
height = image.get_height()
wh = (width, height)
center = (width / 2.0, height / 2.0)
size = (enemy_size,enemy_size * height/width)
vx = 0.5
vy = enemy_size / 2.0
att = 2000
def __init__(self, x, y):
self.x = x
self.x_org = self.x
self.y = y
self.pos = [self.x,self.y]
# Verandert positie vijanden
def update(self):
global lives
if self.y + self.wh[1] >= HEIGHT - BORDER[1]:
lives = 0
if self.x <= self.x_org - CheckX:
self.x = self.x_org - CheckX
self.vx = -self.vx
self.x += self.vx
self.y += self.vy
elif self.x >= self.x_org + CheckX:
self.x = self.x_org + CheckX
self.vx = -self.vx
self.x += self.vx
self.y += self.vy
else:
self.x += self.vx
self.pos = [self.x, self.y]