Lua table read and match efficient - function

My problem is simple, i used to do this in order to check if any of my lines (see photo) bump into any other line (or trail of any other line). But the way i do this now is by doing a lot of if statements, which is not good. So here is the code i used:
function Bumper:draw()
for id,posx1 in pairs(tableposx1) do
posy1 = tableposy1[id]
posx2 = tableposx2[id]
posy2 = tableposy2[id]
posx3 = tableposx3[id]
posy3 = tableposy3[id]
posx4 = tableposx4[id]
posy4 = tableposy4[id]
if (posx1 ~= nil) and (posy1 ~= nil) and
((math.abs(xposplayer1 - posx1) < 5) and (math.abs(yposplayer1 - posy1) < 5))
and (id < (count - 5) and killp1 == "false") then
killp1 = "true"
tint(255, 0, 0, 162)
sprite("Dropbox:kill",xposplayer1,yposplayer1)
noTint()
end
if (posx2 ~= nil) and (posy2 ~= nil) and
((math.abs(xposplayer1 - posx2) < 5) and (math.abs(yposplayer1 - posy2) < 5))
and killp1 == "false" then
killp1 = "true"
tint(255, 0, 0, 162)
sprite("Dropbox:kill",xposplayer1,yposplayer1)
noTint()
end
if (posx3 ~= nil) and (posy3 ~= nil) and
((math.abs(xposplayer1 - posx3) < 5) and (math.abs(yposplayer1 - posy3) < 5))
and killp1 == "false" then
killp1 = "true"
tint(255, 0, 0, 162)
sprite("Dropbox:kill",xposplayer1,yposplayer1)
noTint()
end
if (posx4 ~= nil) and (posy4 ~= nil) and
((math.abs(xposplayer1 - posx4) < 5) and (math.abs(yposplayer1 - posy4) < 5))
and killp1 == "false" then
killp1 = "true"
tint(255, 0, 0, 162)
sprite("Dropbox:kill",xposplayer1,yposplayer1)
noTint()
end
if (posx1 ~= nil) and (posy1 ~= nil) and
((math.abs(xposplayer2 - posx1) < 5) and (math.abs(yposplayer2 - posy1) < 5))
and killp2 == "false" then
killp2 = "true"
tint(0, 29, 255, 162)
sprite("Dropbox:kill",xposplayer2,yposplayer2)
noTint()
end
if (posx2 ~= nil) and (posy2 ~= nil) and
((math.abs(xposplayer2 - posx2) < 5) and (math.abs(yposplayer2 - posy2) < 5))
and (id < (count - 5) and killp2 == "false")then
killp2 = "true"
tint(0, 29, 255, 162)
sprite("Dropbox:kill",xposplayer2,yposplayer2)
noTint()
end
if (posx3 ~= nil) and (posy3 ~= nil) and
((math.abs(xposplayer2 - posx3) < 5) and (math.abs(yposplayer2 - posy3) < 5))
and killp2 == "false" then
killp2 = "true"
tint(0, 29, 255, 162)
sprite("Dropbox:kill",xposplayer2,yposplayer2)
noTint()
end
if (posx4 ~= nil) and (posy4 ~= nil) and
((math.abs(xposplayer2 - posx4) < 5) and (math.abs(yposplayer2 - posy4) < 5))
and killp2 == "false" then
killp2 = "true"
tint(0, 29, 255, 162)
sprite("Dropbox:kill",xposplayer2,yposplayer2)
noTint()
end
if (posx1 ~= nil) and (posy1 ~= nil) and
((math.abs(xposplayer3 - posx1) < 5) and (math.abs(yposplayer3 - posy1) < 5))
and killp3 == "false" then
killp3 = "true"
tint(1, 255, 0, 162)
sprite("Dropbox:kill",xposplayer3,yposplayer3)
noTint()
end
if (posx2 ~= nil) and (posy2 ~= nil) and
((math.abs(xposplayer3 - posx2) < 5) and (math.abs(yposplayer3 - posy2) < 5))
and killp3 == "false" then
killp3 = "true"
tint(1, 255, 0, 162)
sprite("Dropbox:kill",xposplayer3,yposplayer3)
noTint()
end
if (posx3 ~= nil) and (posy3 ~= nil) and
((math.abs(xposplayer3 - posx3) < 5) and (math.abs(yposplayer3 - posy3) < 5))
and (id < (count - 5) and killp3 == "false") then
killp3 = "true"
tint(1, 255, 0, 162)
sprite("Dropbox:kill",xposplayer3,yposplayer3)
noTint()
end
if (posx4 ~= nil) and (posy4 ~= nil) and
((math.abs(xposplayer3 - posx4) < 5) and (math.abs(yposplayer3 - posy4) < 5))
and killp3 == "false" then
killp3 = "true"
tint(1, 255, 0, 162)
sprite("Dropbox:kill",xposplayer3,yposplayer3)
noTint()
end
if (posx1 ~= nil) and (posy1 ~= nil) and
((math.abs(xposplayer4 - posx1) < 5) and (math.abs(yposplayer4 - posy1) < 5))
and killp4 == "false" then
killp4 = "true"
tint(255, 0, 229, 162)
sprite("Dropbox:kill",xposplayer4,yposplayer4)
noTint()
end
if (posx2 ~= nil) and (posy2 ~= nil) and
((math.abs(xposplayer4 - posx2) < 5) and (math.abs(yposplayer4 - posy2) < 5))
and killp4 == "false" then
killp4 = "true"
tint(255, 0, 229, 162)
sprite("Dropbox:kill",xposplayer4,yposplayer4)
noTint()
end
if (posx3 ~= nil) and (posy3 ~= nil) and
((math.abs(xposplayer4 - posx3) < 5) and (math.abs(yposplayer4 - posy3) < 5))
and killp4 == "false" then
killp4 = "true"
tint(255, 0, 229, 162)
sprite("Dropbox:kill",xposplayer4,yposplayer4)
noTint()
end
if (posx4 ~= nil) and (posy4 ~= nil) and
((math.abs(xposplayer4 - posx4) < 5) and (math.abs(yposplayer4 - posy4) < 5))
and id < (count - 5) and killp4 == "false" then
killp4 = "true"
tint(255, 0, 229, 162)
sprite("Dropbox:kill",xposplayer4,yposplayer4)
noTint()
end
end
end
Here is my init:
-- Main
a = 1
gameover = 0
tx = 0
paused = 1
count = 0
stagecount = 0
player1count = 0
player2count = 0
player3count = 0
player4count = 0
-- Random hole times
thistime1 = 0
thistime2 = 0
thistime3 = 0
thistime4 = 0
-- Dead players
killp1 = "false"
killp2 = "false"
killp3 = "false"
killp4 = "false"
kills = 0
-- Touch control
touches = {}
-- Player direction
pi = math.pi
o5pi = 50 * pi
mo5pi = - (50 * pi)
minpi = - (100*pi)
-- Random start direction
r1t = math.random(0,o5pi)
r2t = math.random(mo5pi,0)
r3t = math.random(minpi,mo5pi)
r4t = math.random(o5pi,100*pi)
r1 = r1t / 100
r2 = r2t / 100
r3 = r3t / 100
r4 = r4t / 100
deltar1 = pi / 55
deltar2 = pi / 55
deltar3 = pi / 55
deltar4 = pi / 55
-- Player speed
speed1 = 2.5
speed2 = 2.5
speed3 = 2.5
speed4 = 2.5
-- Player random start position
xposplayer1 = math.random(123,300)
yposplayer1 = math.random(123,300)
xposplayer2 = math.random(123,300)
yposplayer2 = math.random(468,645)
xposplayer3 = math.random(724,901)
yposplayer3 = math.random(468,645)
xposplayer4 = math.random(724,901)
yposplayer4 = math.random(123,300)
-- Player coordinate tables
tableposx1 = {}
tableposy1 = {}
tableposx2 = {}
tableposy2 = {}
tableposx3 = {}
tableposy3 = {}
tableposx4 = {}
tableposy4 = {}
Now i tried doing the following, but failed because i dont now how to use variable variable names:
for id,posx[a] in pairs(tableposx[a]) do
posy[a] = tableposy[a][id]
if ((posx[a] ~= nil) and (posy[a] ~= nil))
and (math.abs(xposplayer[a] - posx[a]) < 5)
and (math.abs(yposplayer[a] - posy[a]) < 5)
and (id < (count - 5))
and (killp[a] == "false")
then
killp[a] = "true"
tintp[a]
sprite("Dropbox:kill",xposplayer[a],yposplayer[a])
noTint()
end
end
a = a + 1
if a = 4 then
a = 1
end
-- EDIT: i use is 4 times, for 4 players!
function Player:draw1()
fill(255, 0, 11, 255)
xposplayer1 = xposplayer1 + speed1 * math.cos(r1)
yposplayer1 = yposplayer1 + speed1 * math.sin(r1)
if player1count == 0 then
thistime1 = math.random(200,500)
end
player1count = player1count + 1
if player1count < thistime1 then
table.insert(tableposx1,count,xposplayer1)
table.insert(tableposy1,count,yposplayer1)
tint(255, 0, 0, 162)
ellipse(xposplayer1,yposplayer1,10,10)
noTint()
elseif player1count > thistime1 then
tint(255, 0, 0, 162)
ellipse(xposplayer1,yposplayer1,5,5)
noTint()
if player1count > thistime1 + 20 then
player1count = 0
end
end
end
-- EDIT
How should i do this correctly? Thanks in advance!
Image:

You probably don't really want variable variable names like you said, but you can do it...
All globals are accessible by table named _G, and you can access your global variables by doing this:
_G['killp1']
_G['killp2']
-- etc
You can then use string manipulation as usual.
local i = 1
_G['killp' .. tostring(i)] -- same as _G['killp1']
i = i + 1
_G['killp' .. tostring(i)] -- same as _G['killp2']
But this is going to get really messy, fast. What you probably want to do instead is start using objects. You object might look something like this:
Linething = { x = 0, y = 0, dead = false, speed = 2.5 }
function Linething:new(o)
o = o or {}
setmetatable(o, self)
self.__index = self
return o
end
function Linething:checkCollision(other)
if self.x - other.x < 5 and self.y - other.y < 5 then
self.dead = true
-- other stuff
end
end
function Linething:update(delta_t)
-- update the game logic
self.x = self.x + self.speed * cos(self.angle) * delta_t
self.y = self.y + self.speed * sin(self.angle) * delta_t
end
function Linething:draw()
-- do line drawing here
tint(255, 0, 0, 162)
ellipse(self.x, self.y, 10, 10)
noTint()
-- etc
end
-- in main:
linething1 = Linething:new()
linething2 = Linething:new()
linething1.checkCollision(linething2)
EDIT: Typically you want to seperate the game logic from the rendering. Most games have a loop that looks like this:
function main_loop()
while true do
delta_t = get_change_in_time()
update_all(delta_t)
draw_all()
end
end
-- where update_all is something like this:
function update_all(delta_t)
player1:update(delta_t)
player2:update(delta_t)
-- things in a table:
for _, x in pairs(table_of_x) do
x:update(delta_t)
end
end
-- and draw all is basically the same
function draw_all()
player1:draw()
player2:draw()
-- things in a table:
for _, x in pairs(table_of_x) do
x:draw()
end
end
It looks like your Player object has-a Linething object. So you might want to add a Linething object to the Player object and change Player:draw() to call players_linething:draw(). Then you can have 4 Player objects, which each have a Linething object. Does that make sense?

The problem is that you're using variables with subscripts (player1, player2, etc.) rather than arrays (player[1], player[2], etc.) which makes it impossible to iterate over them in a loop.
You should also be grouping related items together. Rather than player 1 being represented by a bunch of global variables:
player1count = 0
speed1 = 2.5
Those things should be organized into a table:
player1.count = 0
speed1.speed = 2.5
And, as mentioned before, any time you have a bunch of variables that vary by subscript, you should be using an array (or more generally, some kind of iterable list type, which in Lua happens to be a table/array):
players = {}
-- initialize players
for i=1,NUM_PLAYERS do
players[i] = {
count = 0,
speed = 2.5
}
end
If you apply this generally to your program, your huge if statement is going to naturally disappear, being replaced by a relatively small, nested for loop.

I have not read everything but in your last snippet:
You cannot do for id,posx[a], because the variables assigned by a for loop are local. To fix it replace instances of posx[a] by a local variable name such as posx_a.
There is a typo here: if a = 4 then (you mean ==).
This line means nothing: tintp[a].

Related

Weird user-defined function behavior in Octave

In Octave why does my function here always return 1?
Code:
function val = g2(x)
sigma = 0.1;
if (x <= -8)
val = exp(-0.5*((x+8)^2)/(sigma^2));
endif
if (x >= 8)
val = exp(-0.5*((x-8)^2)/(sigma^2));
endif
if (-8 < x < 8)
val = 1;
endif
endfunction
-8 < x < 8 is evaluated as (-8 < x) < 8, which is either true < 8 or false < 8, depending on the value of x. Both of which are true, because false is 0 in a numerical situation, and true is 1. So the last conditional statement is always executed. In Octave you’d write (-8 < x) && (x < 8).
But better would be to write your code as
function val = g2(x)
sigma = 0.1;
if x <= -8
val = exp(-0.5*((x+8)^2)/(sigma^2));
elseif x >= 8
val = exp(-0.5*((x-8)^2)/(sigma^2));
else
val = 1;
endif
endfunction

Problem creating new enemies when player levels up

i'm working on a simple clone of Space Invaders for an University project. The idea is that when the players levels up, the amount of enemies increase, but when i try to do it, the enemies creates infinitly while the stablished condition is true. I can't dettect the problem, so if one of you can help me, i'll apreciate it.
import random
import csv
import operator
import pygame
import time
from pygame import mixer
# Intialize the pygame
pygame.init()
# create the screen
screen = pygame.display.set_mode((800, 600))
# Background
background = pygame.image.load('background.png')
# Sound
mixer.music.load("background.wav")
mixer.music.play(-1)
#Reloj
clock = pygame.time.Clock()
# Caption and Icon
pygame.display.set_caption("Space Invader")
icon = pygame.image.load('ufo.png')
pygame.display.set_icon(icon)
# Score
score_value = 0
level_value = 1
level_up_value = ""
font = pygame.font.Font('freesansbold.ttf', 20)
game_over = False
high_scores = []
names = []
with open('high_scores.csv') as csvfile:
reader = csv.reader(csvfile)
sortedlist = sorted(reader, key=operator.itemgetter(1), reverse=True)
for i in sortedlist:
names.append(i[0])
high_scores.append(i[1])
scoreX = 10
scoreY = 10
level_textX = 10
level_textY = 80
levelX = 10
levelY = 40
# Game Over
over_font = pygame.font.Font('freesansbold.ttf', 64)
menu_font = pygame.font.Font('freesansbold.ttf', 48)
scores_font = pygame.font.Font('freesansbold.ttf', 45)
#Número de vidas
num_vidas = 3
font = pygame.font.Font('freesansbold.ttf', 32)
vidasX = 650
vidasY = 10
# Player
playerImg = pygame.image.load('player.png')
playerX = 370
playerY = 480
playerX_change = 0
# Enemy
enemyImg = []
bichoImg = []
meteoroImg = []
enemyX = []
enemyY = []
enemyY_change = []
bichoX = []
bichoY = []
bichoY_change = []
meteoroX = []
meteoroY = []
meteoroY_change = []
num_of_enemies_10 = 5
num_of_enemies_20 = 4
num_of_enemies_30 = 3
for i in range(num_of_enemies_10):
enemyImg.append(pygame.image.load('enemy.png'))
enemyX.append(random.randint(0, 736))
enemyY.append(random.randint(50, 150))
enemyY_change.append(0.5)
for i in range(num_of_enemies_20):
bichoImg.append(pygame.image.load('bicho.png'))
bichoX.append(random.randint(0, 736))
bichoY.append(random.randint(10, 120))
bichoY_change.append(0.5)
for i in range(num_of_enemies_30):
meteoroImg.append(pygame.image.load('meteoro.png'))
meteoroX.append(random.randint(0, 736))
meteoroY.append(random.randint(0, 150))
meteoroY_change.append(0.5)
# Bullet
# Ready - You can't see the bullet on the screen
# Fire - The bullet is currently moving
bulletImg = pygame.image.load('bullet.png')
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = 10
bullet_state = "ready"
def show_score(x, y):
score = font.render("Score : " + str(score_value), True, (255, 255, 255))
screen.blit(score, (x, y))
def show_level(x, y):
level = font.render("Level: " + str(level_value), True, (255, 255, 255))
screen.blit(level, (x, y))
def level_up_text(x, y):
level_text = font.render(level_up_value, True, (255, 255, 0))
screen.blit(level_text, (level_textX, level_textY))
def show_vidas(x, y):
vidas = font.render("Vidas : " + str(num_vidas), True, (255, 255, 255))
screen.blit(vidas, (x, y))
def game_over_text():
over_text = over_font.render("GAME OVER", True, (255, 255, 255))
screen.blit(over_text, (200, 250))
def player(x, y):
screen.blit(playerImg, (x, y))
def enemy(x, y, i):
screen.blit(enemyImg[i], (x, y))
def bicho(x, y, i):
screen.blit(bichoImg[i], (x, y))
def meteoro(x, y, i):
screen.blit(meteoroImg[i], (x, y))
def fire_bullet(x, y):
global bullet_state
bullet_state = "fire"
screen.blit(bulletImg, (x + 16, y + 10))
#Colisiones para cada tipo de enemigo
def isCollision1(enemyX, enemyY, bulletX, bulletY):
distance = math.sqrt(math.pow(enemyX - bulletX, 2) + (math.pow(enemyY - bulletY, 2)))
if distance < 27:
return True
else:
return False
def isCollision2(bichoX, bichoY, bulletX, bulletY):
distance = math.sqrt(math.pow(bichoX - bulletX, 2) + (math.pow(bichoY - bulletY, 2)))
if distance < 27:
return True
else:
return False
def isCollision3(meteoroX, meteoroY, bulletX, bulletY):
distance = math.sqrt(math.pow(meteoroX - bulletX, 2) + (math.pow(meteoroY - bulletY, 2)))
if distance < 27:
return True
else:
return False
# Pause Loop
def show_pause():
paused = True
while paused:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
pause_title = menu_font.render("PAUSED", True, (255, 255, 0))
pauseRect = pause_title.get_rect()
pauseRect.centerx = screen.get_rect().centerx
pauseRect.centery = screen.get_rect().centery - 50
screen.blit(pause_title, pauseRect)
high_title = menu_font.render("HIGH SCORES", True, (255, 255, 255))
highRect = high_title.get_rect()
highRect.centerx = screen.get_rect().centerx
highRect.centery = screen.get_rect().centery + 50
screen.blit(high_title, highRect)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
paused = False
break
if event.type == pygame.MOUSEBUTTONDOWN:
mpos = pygame.mouse.get_pos()
if highRect.collidepoint(mpos):
show_high_scores_menu()
break
pygame.display.update()
# High Scores Loop
def show_high_scores_menu():
high_scores_menu = True
global high_scores, names
high_scores.clear()
names.clear()
with open('high_scores.csv') as csvfile:
reader = csv.reader(csvfile)
sortedlist = sorted(reader, key=operator.itemgetter(1), reverse=True)
for i in sortedlist:
names.append(i[0])
high_scores.append(i[1])
while high_scores_menu:
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
high_title = menu_font.render("HIGH SCORES", True, (255, 255, 0))
highRect = high_title.get_rect()
highRect.centerx = screen.get_rect().centerx
highRect.centery = 100
screen.blit(high_title, highRect)
score1 = scores_font.render(names[0] + " : " + str(high_scores[0]), True, (255, 255, 255))
score1Rect = score1.get_rect()
score1Rect.centerx = screen.get_rect().centerx
score1Rect.centery = 250
screen.blit(score1, score1Rect)
score2 = scores_font.render(names[1] + " : " + str(high_scores[1]), True, (255, 255, 255))
score2Rect = score1.get_rect()
score2Rect.centerx = screen.get_rect().centerx
score2Rect.centery = 300
screen.blit(score2, score2Rect)
score3 = scores_font.render(names[2] + " : " + str(high_scores[2]), True, (255, 255, 255))
score3Rect = score3.get_rect()
score3Rect.centerx = screen.get_rect().centerx
score3Rect.centery = 350
screen.blit(score3, score3Rect)
score4 = scores_font.render(names[3] + " : " + str(high_scores[3]), True, (255, 255, 255))
score4Rect = score4.get_rect()
score4Rect.centerx = screen.get_rect().centerx
score4Rect.centery = 400
screen.blit(score4, score4Rect)
score5 = scores_font.render(names[4] + " : " + str(high_scores[4]), True, (255, 255, 255))
score5Rect = score1.get_rect()
score5Rect.centerx = screen.get_rect().centerx
score5Rect.centery = 450
screen.blit(score5, score5Rect)
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_ESCAPE:
high_scores_menu = False
show_pause()
break
pygame.display.update()
def save_high_scores():
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
name = ""
while len(name) < 3:
for event in pygame.event.get():
if event.type == pygame.KEYDOWN:
if event.unicode.isalpha():
name += event.unicode
elif event.key == pygame.K_BACKSPACE:
name = name[:-1]
name = name.upper()
screen.fill((0, 0, 0))
screen.blit(background, (0, 0))
high_title = menu_font.render("High Score!", True, (255, 255, 0))
highRect = high_title.get_rect()
highRect.centerx = screen.get_rect().centerx
highRect.centery = 100
screen.blit(high_title, highRect)
inpt = font.render("Enter a 3-letter name", True, (255, 255, 255))
inptRect = inpt.get_rect()
inptRect.centerx = screen.get_rect().centerx
inptRect.centery = 200
screen.blit(inpt, inptRect)
namedisplay = menu_font.render(name, True, (255, 255, 255))
namedisplayRect = namedisplay.get_rect()
namedisplayRect.center = screen.get_rect().center
screen.blit(namedisplay, namedisplayRect)
pygame.display.update()
#replace lowest
lowest = high_scores[0]
lowest_index = 0
for i in range(len(high_scores)):
if high_scores[i] <= lowest:
lowest = high_scores[i]
lowest_index = i
high_scores[lowest_index] = score_value
names[lowest_index] = name
with open('high_scores.csv', 'w',newline='') as csvfile:
writer = csv.writer(csvfile)
for i in range(len(names)):
writer.writerow([str(names[i]), str(high_scores[i])])
show_high_scores_menu()
BLACK = (0, 0, 0)
#Agregar imágenes para explosión
explosión_anim = []
for i in range(9):
file = "Explosión/Explosión 0{}.png".format(i)
img = pygame.image.load(file).convert()
img.set_colorkey(BLACK)
img_scale = pygame.transform.scale(img, (70, 70))
explosión_anim.append (img_scale)
def explosión1():
image = explosión_anim[0]
center = image.get_rect()
frame = 0
last_update = pygame.time.get_ticks()
frame_rate = 50 #Velocidad de la explosión
screen.blit(image, (enemyX[i], enemyY[i]))
now = pygame.time.get_ticks()
if now - last_update > frame_rate:
last_update = now
frame += 1
if frame == len(explosión_anim):
kill()
else:
center = rect.center
image = explosión_anim[frame]
rect = image.get_rect()
rect.center = center
def explosión2():
image = explosión_anim[0]
center = image.get_rect()
frame = 0
last_update = pygame.time.get_ticks()
frame_rate = 50 #Velocidad de la explosión
screen.blit(image, (bichoX[i], bichoY[i]))
now = pygame.time.get_ticks()
if now - last_update > frame_rate:
last_update = now
frame += 1
if frame == len(explosión_anim):
kill()
else:
center = rect.center
image = explosión_anim[frame]
rect = image.get_rect()
rect.center = center
def explosión3():
image = explosión_anim[0]
center = image.get_rect()
frame = 0
last_update = pygame.time.get_ticks()
frame_rate = 50 #Velocidad de la explosión
screen.blit(image, (meteoroX[i], meteoroY[i]))
now = pygame.time.get_ticks()
if now - last_update > frame_rate:
last_update = now
frame += 1
if frame == len(explosión_anim):
kill()
else:
center = rect.center
image = explosión_anim[frame]
rect = image.get_rect()
rect.center = center
# Game Loop
en_partida = True
while en_partida:
clock.tick(60)
en_final = False
# RGB = Red, Green, Blue
screen.fill((0, 0, 0))
# Background Image
screen.blit(background, (0, 0))
# if player levels up
if score_value < 40:
level_value = 1
elif score_value <= 80:
level_value = 2
elif score_value <= 120:
level_value = 3
elif score_value <= 160:
level_value = 4
if (score_value >= 40 and score_value <= 42):
level_up_value = "LEVEL UP!"
elif (score_value >= 80 and score_value <= 82):
level_up_value = "LEVEL UP!"
elif (score_value >= 120 and score_value <= 122):
level_up_value = "LEVEL UP!"
else:
level_up_value = ""
for event in pygame.event.get():
if event.type == pygame.QUIT:
en_partida = False
# if keystroke is pressed check whether its right or left
if event.type == pygame.KEYDOWN:
if event.key == pygame.K_LEFT:
playerX_change = -5
if event.key == pygame.K_RIGHT:
playerX_change = 5
if event.key == pygame.K_SPACE:
if bullet_state == "ready":
bulletSound = mixer.Sound("laser.wav")
bulletSound.play()
# Get the current x cordinate of the spaceship
bulletX = playerX
fire_bullet(bulletX, bulletY)
if event.type == pygame.KEYUP:
if event.key == pygame.K_LEFT or event.key == pygame.K_RIGHT:
playerX_change = 0
# 5 = 5 + -0.1 -> 5 = 5 - 0.1
# 5 = 5 + 0.1
playerX += playerX_change
if playerX <= 0:
playerX = 0
elif playerX >= 736:
playerX = 736
# Enemy Movement
for i in range(num_of_enemies_10):
# Game Over
enemyY[i] += enemyY_change[i]
if enemyY[i] > 440:
for j in range(num_of_enemies_10):
enemyY[j] = 2000
game_over_text()
break
for i in range(num_of_enemies_20):
# Game Over
bichoY[i] += bichoY_change[i]
if bichoY[i] > 440:
for j in range(num_of_enemies_20):
bichoY[j] = 2000
game_over_text()
break
for i in range(num_of_enemies_30):
# Game Over
meteoroY[i] += meteoroY_change[i]
if meteoroY[i] > 440:
for j in range(num_of_enemies_30):
meteoroY[j] = 2000
game_over_text()
break
# Collision
collision1 = isCollision1(enemyX[i], enemyY[i], bulletX, bulletY)
collision2 = isCollision2(bichoX[i], bichoY[i], bulletX, bulletY)
collision3 = isCollision3(meteoroX[i], meteoroY[i], bulletX, bulletY)
enemy(enemyX[i], enemyY[i], i)
bicho(bichoX[i], bichoY[i], i)
meteoro(meteoroX[i], meteoroY[i], i)
if collision1:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
explosión1()
bulletY = 480
bullet_state = "ready"
score_value += 10
num_of_enemies_10 -= 1
if collision2:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
explosión2()
bulletY = 480
bullet_state = "ready"
score_value += 20
num_of_enemies_20 -= 1
if collision3:
explosionSound = mixer.Sound("explosion.wav")
explosionSound.play()
explosión3()
bulletY = 480
bullet_state = "ready"
score_value += 30
num_of_enemies_30 -= 1
#Aumento de enemigos por nivel
enemy_created = False
flag = False
if(level_value == 2 and flag == True):
flag = True
enemyX[i] = random.randint(0,736)
enemyY[i] = random.randint(50,150)
enemy(enemyX[i], enemyY[i], i)
enemy_created = True
# Bullet Movement
if bulletY <= 0:
bulletY = 480
bullet_state = "ready"
if bullet_state == "fire":
fire_bullet(bulletX, bulletY)
bulletY -= bulletY_change
player(playerX, playerY)
show_score(scoreX, scoreY)
show_level(levelX, levelY)
level_up_text(levelX + 100, levelY)
show_vidas(vidasX, vidasY)
pygame.display.update()
pygame.quit()
Set the flag before the game loop:
# Game Loop
flag = True # set flag here
en_partida = True
while en_partida:
clock.tick(60)
....................
#Aumento de enemigos por nivel
enemy_created = False
if(level_value == 2 and flag == True): # check flag
flag = False # reset flag
enemyX[i] = random.randint(0,736)
enemyY[i] = random.randint(50,150)
enemy(enemyX[i], enemyY[i], i)
enemy_created = True

table returning nil value when calling function

I'm trying to pass a table through several functions and return it, but it only works to a certain degree. I'm almost sure it has to do something with the scoping, but I can't work it out since I'm new with LUA.
I tried putting the table in line 1 and setting it global, but to no avail.
Error: bag argument: expected table but got nil.
function returnToTunnel(movementTable)
for i = table.maxn(movementTable), 1, -1 do --this is where I get the error.
if (movementTable[i] == 1) then
turtle.down()
elseif (movementTable[i] == 2) then
turtle.up()
elseif (movementTable[i] == 3) then
turtle.back()
turtle.turnRight()
elseif (movementTable[i] == 4) then
turtle.back()
turtle.turnLeft()
elseif (movementTable[i] == 5) then
turtle.back()
end
end
end
function mineOre(locationParam, movementTable)
if (locationParam == 1) then
turtle.digUp()
turtle.suckUp()
turtle.up()
table.insert(movementTable, 1)
elseif (locationParam == 2) then
turtle.digDown()
turtle.suckDown()
turtle.down()
table.insert(movementTable, 2)
elseif (locationParam == 3) then
turtle.turnLeft()
turtle.dig()
turtle.suck()
turtle.forward()
table.insert(movementTable, 3)
elseif (locationParam == 4) then
turtle.turnRight()
turtle.dig()
turtle.suck()
turtle.forward()
table.insert(movementTable, 4)
elseif (locationParam == 5) then
turtle.dig()
turtle.suck()
turtle.forward()
table.insert(movementTable, 5)
end
locationParam = oreCheck()
if (locationParam > 0) then
mineOre(locationParam, movementTable)
else
return movementTable
end
end
function digTunnel(tunnelLengthParam)
local oreFound
local movement = {}
for i = 1, tunnelLengthParam do
turtle.dig()
turtle.forward()
oreFound = oreCheck()
if (oreFound > 0) then
movement = mineOre(oreFound, movement)
returnToTunnel(movement)
end
if ((i % 2) == 1) then
turtle.digUp()
turtle.up()
elseif ((i % 2) == 0) then
turtle.digDown()
turtle.down()
end
oreFound = oreCheck()
if (oreFound > 0) then
movement = mineOre(oreFound, movement)
returnToTunnel(movement)
end
end
end
So, the digTunnel function calls the other two functions mineOre and returnToTunnel.
I've been looking in the LUA manual and several websites but can't figure it out.
Thank you for your help!
Your function mineOre does not return a table but nil, when locationParam is > 0.
if (locationParam > 0) then
mineOre(locationParam, movementTable)
else
return movementTable
end
Hence this will cause a nil value end up in table.maxn
movement = mineOre(oreFound, movement)
returnToTunnel(movement)

PyGame surface locked during blit [duplicate]

I am trying to draw text to a screen in a space above a bunch of rects that are all in the 2d array square. When i try and draw text to the screen it says that "Surfaces must not be locked during blit."
I have tried unlocking, it makes no difference.
import sys, time, random, pygame
from pygame import *
from time import time,sleep
pygame.init()
global isDragging, inDrag, rightDrag, lastDrag, inDragRight, mouseX,mouseY, borderHeight
isDragging = False
isAuto = False
inDrag= False
inDragRight = False
isFilling = False
done = False
lastDrag = None
rightDrag = None
tickTime = 300
font = pygame.font.SysFont(None, 12,False,False)
dragDelay = 2
BLACK = ( 0, 0, 0)
WHITE = ( 255, 255, 255)
GREEN = ( 0, 255, 0)
RED = ( 255, 0, 0)
PINK = ( 255, 150, 200)
BLUE = ( 0, 0, 255)
RED = GREEN
width, height, margin = 100, 100, 1
noWidth, noHeight = 6,6
speed = [2, 2]
borderHeight = 50
size = (width*noWidth,height*noHeight + borderHeight)
screen = pygame.display.set_mode(size)
pygame.display.set_caption("PieStone")
clock = pygame.time.Clock()
pixArray = pygame.PixelArray(screen)
font = pygame.font.SysFont("monospace", 15)
word = font.render("test", 1, (0, 0, 0))
class Null:
pass
square = [[Null() for i in range(noHeight)]for i in range(noWidth)]
for d1 in range(noWidth):
for d2 in range(noHeight):
square[d1][d2].man = False
square[d1][d2].visits = 0
square[d1][d2].colour = BLACK
square[d1][d2].margin = 1
a = 1
i = 1
def text(word,size,pos1,pos2,pos3):
word = font.render(str(word),size,(pos1,pos2,pos3))
return word
def colide(obj,mouseX,mouseY):
if obj.collidepoint(mouseX,mouseY) == 1:
return True
else:
return False
def click(mouseX,mouseY):
#rint("left")
global inDrag,lastDrag
for d1 in range(noWidth):
for d2 in range(noHeight):
if colide(square[d1][d2].rect,mouseX,mouseY):
square[d1][d2].man = True
#print("square",d1,d2,"has been clicked")
try:
if square[d1][d2] != lastDrag:
inDrag = True
lastDrag = square[d1][d2]
else:
inDrag = False
except UnboundLocalError:
print("error")
lastDrag = square[d1][d2]
#print(inDrag)
if square[d1][d2].margin == 0 and inDrag:
square[d1][d2].margin = 1
square[d1][d2].visits = square[d1][d2].visits + 1
elif square[d1][d2].margin == 1 and inDrag:
square[d1][d2].margin = 0
square[d1][d2].visits = square[d1][d2].visits + 1
break
'''if square[d1][d2].visits >= 5 and square[d1][d2].colour == BLACK:
square[d1][d2].visits = 0
square[d1][d2].colour = RED
elif square[d1][d2].visits >= 5 and square[d1][d2].colour == RED:
square[d1][d2].visits = 0
square[d1][d2].colour = BLACK'''
def rightClick(mouseX,mouseY):
#print("right")
global inDragRight, lastRight
for d1 in range(noWidth):
for d2 in range(noHeight):
if colide(square[d1][d2].rect,mouseX,mouseY):
square[d1][d2].man = True
#print("colide")
try:
if square[d1][d2] != lastRight:
inDragRight = True
lastRight = square[d1][d2]
else:
inDragRight = False
except:
print("error")
lastRight = square[d1][d2]
#print(inDragRight)
if square[d1][d2].colour == RED and inDragRight:
square[d1][d2].colour = BLACK
#print("black")
elif square[d1][d2].colour == BLACK and inDragRight:
square[d1][d2].colour = RED
#print("red")
break
while not done:
screen.blit(word, (0, 0))
(mouseX,mouseY) = pygame.mouse.get_pos()
#print(str(mouseX)+",",mouseY)
for event in pygame.event.get(): # User did something
if event.type == pygame.QUIT: # If user clicked close
done = True # Flag that we are done so we exit this loop
elif event.type == pygame.MOUSEBUTTONDOWN:
#print(mouseX,mouseY)
if pygame.mouse.get_pressed()[0] == 1:
isDragging = True
if pygame.mouse.get_pressed()[2] == 1:
isFilling = True
elif pygame.mouse.get_pressed()[1] == 1:
isAuto = True
#print(pygame.mouse.get_pressed())
elif event.type == pygame.MOUSEBUTTONUP:
#print("up")
isDragging = False
isFilling = False
lastDrag = None
lastRight = False
if pygame.mouse.get_pressed()[0] == 1:
isDragging = True
if pygame.mouse.get_pressed()[2] == 1:
isFilling = True
if isAuto:
rnd1 = random.randint(0,1)
if rnd1 == 1:
isDragging = True
isFilling = False
else:
isDragging = False
isFilling = True
(mouseX,mouseY) = (random.randint(0,width*noWidth),random.randint(0,height*noHeight)+borderHeight)
#print(mouseX,mouseY)
if isDragging:
click(mouseX,mouseY)
if isFilling:
rightClick(mouseX,mouseY)
screen.fill(WHITE)
# --- Game logic should go here
i = 0
for d1 in range(noWidth):
if noHeight % 2 == 0:
'''if i == 0:
i = 1
else:
i = 0'''
for d2 in range(noHeight):
#if i % a == 0:
try:
if i == 0:
pass
elif i == 1:
pass
except AttributeError:
print("AttributeError")
square[d1][d2].margin = random.randint(0,1)
#print(square[d1][d2].visits)
square[d1][d2].rect = pygame.draw.rect(screen, square[d1][d2].colour, [(d1*width), ((d2*height)+borderHeight),width,(height)],square[d1][d2].margin)
#print("d1*width:",d1*width,"d2*height:",d2*height,"d1*width+width:",d1*width+width,"d2*height+height:",d2*height+height)
pygame.display.flip()
clock.tick(tickTime)
# Close the window and quit.
# If you forget this line, the program will 'hang'
# on exit if running from IDLE.
pygame.quit()
You're using a PixelArray:
pixArray = pygame.PixelArray(screen)
But using a PixelArray locks your Surface, as stated in the documentation:
During its lifetime, the PixelArray locks the surface, thus you explicitly have to delete it once its not used anymore and the surface should perform operations in the same scope.
Just remove the line, since you're not using it anyway.

Pygame Snake food generator

I'm currently in the process of creating a Snake game and I want to create a food generator that generates an apple every 10 seconds based on my in-game timer. The timer counts down from 60 to 0(when the game ends) and I want an new apple to generate every 10 seconds, keeping the old one even if it hasn't been eaten. I don't know how to approach this and could use some help. Here is my full program.
Edit: this is a beginner Computer Science school project so the more basic the better.
import random
import pygame
pygame.init()
#---------------------------------------#
#
# window properties #
width = 640 #
height = 480
game_window=pygame.display.set_mode((width,height))
black = ( 0, 0, 0) #
#---------------------------------------#
# snake's properties
outline=0
body_size = 9
head_size = 10
apple_size = 8
speed_x = 8
speed_y = 8
dir_x = 0
dir_y = -speed_y
segx = [int(width/2.)]*3
segy = [height, height + speed_y, height + 2*speed_y]
segments = len(segx)
apple_counter = 0
grid_step = 8
regular_font = pygame.font.SysFont("Andina",18)
blue = [11, 90, 220]
clock = pygame.time.Clock()
time = 60
fps = 25
time = time + 1.0/fps
text = regular_font.render("Time from start: "+str(int(time)), 1, blue)
text2 = regular_font.render("Score: "+str(int(apple_counter)), 1, blue)
apple_x = random.randrange(0, 640, grid_step)
apple_y = random.randrange(0, 480, grid_step)
apple_colour = (255,0,0)
def redraw_game_window():
game_window.fill(black)
for i in range(segments):
segment_colour = (random.randint(1,50),random.randint(100,150),random.randint(1,50))
head_colour = (random.randint(180,220),random.randint(180,220),random.randint(1,15))
apple_colour = (255,0,0)
pygame.draw.circle(game_window, segment_colour, (segx[i], segy[i]), body_size, outline)
pygame.draw.circle(game_window, head_colour, (segx[0], segy[0]), head_size, outline)
game_window.blit(text, (530, 20))
game_window.blit(text2, (30, 20))
pygame.draw.circle(game_window, apple_colour, (apple_x, apple_y), apple_size, outline)
pygame.display.update()
exit_flag = False
print "Use the arrows and the space bar."
print "Hit ESC to end the program."
########################################################## TIMER/CONTROLS
while exit_flag == False:
redraw_game_window()
clock.tick(fps)
time = time - 1.00/fps
text = regular_font.render("Time: "+str(int(time)), 1, blue)
text2 = regular_font.render("Score: "+str(int(apple_counter)), 1, blue)
if time < 0.1:
print "Game Over"
exit_flag = True
pygame.event.get()
keys = pygame.key.get_pressed()
if time ==
if keys[pygame.K_ESCAPE]:
exit_flag = True
if keys[pygame.K_LEFT] and dir_x != speed_x:
dir_x = -speed_x
dir_y = 0
if keys[pygame.K_RIGHT] and dir_x != -speed_x:
dir_x = speed_x
dir_y = 0
if keys[pygame.K_UP] and dir_y != speed_x:
dir_x = 0
dir_y = -speed_y
if keys[pygame.K_DOWN] and dir_y != -speed_x:
dir_x = 0
dir_y = speed_y
############################################################ SNAKE MOVEMENT
for i in range(segments-1,0,-1):
segx[i]=segx[i-1]
segy[i]=segy[i-1]
segx[0] = segx[0] + dir_x
segy[0] = segy[0] + dir_y
############################################################ COLLISION
for i in range(segments-1, 3, -1):
if segments > 3:
if segx[0] == segx[i] and segy[0] == segy[i]:
print "You have collided into yourself, Game Over."
exit_flag = True
############################################################# BORDERS
if segx[0] > 640 or segx[0] < 0:
print "Game Over, you left the borders."
break
if segy[0] > 480 or segy[0] < 0:
print "Game Over, you left the borders."
break
############################################################# APPLE DETECT
for i in range (0 , 13):
if segx[0] == apple_x + i and segy[0] == apple_y + i:
segments = segments + 1
segx.append(segx[-1])
segy.append(segy[-1])
apple_counter = apple_counter + 1
if segx[0] == apple_x - i and segy[0] == apple_y - i:
segments = segments + 1
segx.append(segx[-1])
segy.append(segy[-1])
apple_counter = apple_counter + 1
#############################################################
pygame.quit()
You either
A) use pygame.time.set_timer to call a function every 10 seconds to spawn food, and every 60 seconds to end the round.
or
B) compare get_ticks()
def new_round():
last_apple = pygame.time.get_ticks() + 10*1000
while true:
now = pygame.time.get_ticks()
if now - last_apple >= 1000:
spawn_apple()
last_apple = now
if now - round_start >= 60*1000:
round_end()