Черновая версия игры Arcanoid, популярной раньше на тетрисах и NES.
При разработке возникла проблема коллизии спрайтов. Для движения шарика у меня выставлен очень маленький sprite delay, в связи с чем основная часть программы не всегда успевает обработать коллизию, и спрайт улетает за нижнюю доску. Решить вроде бы удалось костылями типа дополнительной проверки координат доски, но сомневаюсь, что это лучшее решение. Также были проблемы с непробиваемыми блоками, от которых шар просто должен отскакивать, не удаляя их с поля: иногда, в определенных местах коллизии, шар просто не успевал отскочить и начинал дергаться из стороны в сторону уже внутри блока. Опять же вроде бы решил, но снова костылями.
Разработкой игры с фоновыми процессами занимаюсь впервые, очень прошу проанализировать код и указать на ошибки. Заранее спасибо!
GRAPHICS
bgr=0.2!bgg=0.2!bgb=0.2
GRAPHICS CLEAR bgr,bgg,bgb
SET ORIENTATION PORTRAIT
w=SCREEN_WIDTH()
h=SCREEN_HEIGHT()
bat_wid=100
ball_size=8
bl_w=w/12
DEF score(s)
SPRITE "score" BEGIN
GRAPHICS CLEAR .bgr,.bgg,.bgb
DRAW COLOR 1,1,1
DRAW TEXT "Счёт: "&s AT .bl_w/3,20
SPRITE END
ENDDEF
DEF lifes(s)
DRAW COLOR 1,1,1
SPRITE "lifes_spent" BEGIN
GRAPHICS CLEAR .bgr,.bgg,.bgb
DRAW TEXT "x"&s AT 0,0
SPRITE END
ENDDEF
REFRESH OFF
SPRITE "score" BEGIN bl_w*3,45
DRAW TEXT "Счёт: 0" AT bl_w/3, 20
SPRITE END
SPRITE "kvadrat" BEGIN bat_wid,20
FILL COLOR 0,0,0
FILL RECT 0,0 TO bat_wid-1,19
FILL COLOR 0,0.2,0.8
FILL RECT 2,2 TO bat_wid-3,17
SPRITE END
SPRITE "krug" BEGIN ball_size*2,ball_size*2 'летающий круг
FILL COLOR 1,1,1
FILL CIRCLE ball_size, ball_size SIZE ball_size-1
FILL COLOR 1,0.5,0.5
FILL CIRCLE ball_size, ball_size SIZE ball_size-3
SPRITE END
SPRITE "krug" ORDER 100
SPRITE "krug" COPY "lifes"
SPRITE "lifes" AT w-(bl_w), 20
SPRITE "lifes" SHOW
SPRITE "lifes_spent" BEGIN bl_w*2-(ball_size*2), 20
SPRITE END
SPRITE "lifes_spent" AT w-(bl_w)+(ball_size*2), 20
SPRITE "lifes_spent" SHOW
SPRITE "pol" BEGIN w,10
FILL COLOR 1,0,0
FILL RECT 0,0 TO w,10
SPRITE END
SPRITE "fg" BEGIN w,h
FILL COLOR 0,0,0
FILL RECT 0,0 TO w,h
SPRITE END
SPRITE "fg" ALPHA 0.5
SPRITE "pol" AT 0,h-10
SPRITE "pol" SHOW
SPRITE "krug" DELAY 0.005
SPRITE "score" SHOW
SPRITE "krug" DELAY 0.0015
restart:
level_number=1
bl=0
speed=2
life=3
s=0
score(s)
lifes(life)
TIME RESET
FOR i=1 TO 20
IF LABEL_EXISTS(STR$(i))=0 THEN BREAK
level_max=i
NEXT i
level_init:
IF level_number>1 THEN s+=(100-INT(TIMER()/1000))*10
IF level_number>level_max THEN restart
OPTION SPRITE POS NORMAL
REFRESH OFF
block_count=0
bl_max=0
bl=0
cells=0
speed+=0.2
score(s)
began=0
ON level_number RESTORE TO 1,2,3
DIM level(8,8)
FOR i=0 TO 7 'строка
FOR j=0 TO 7 'столбец
READ level(i,j)
IF level(i,j)=9 THEN !i=7!j=7!ENDIF
IF level(i,j)>0 THEN block_count+=1
IF level(i,j)=1 THEN bl_max+=1
NEXT j
NEXT i
DIM white_blocks(block_count*10)
DEF block_init(n,y,r,g,b)
SPRITE n BEGIN .bl_w,y
FILL COLOR r,g,b
FILL RECT 0,0 TO .bl_w-2,y-2
FILL COLOR r-0.1,g-0.1,b-0.1
FILL RECT 0,y*0.5-1 TO .bl_w-3,3
DRAW COLOR 0.3,0.3,0.3
DRAW RECT 0,0 TO .bl_w-1,y-1
SPRITE END
ENDDEF
!r=RND(1.0)!g=RND(1.0)!b=RND(1.0)
n=1
FOR i=0 TO 7
FOR j=0 TO 7
block_pos=bl_w+bl_w*j
IF level(i,j)<>0 AND level(i,j)<>9 THEN
IF level(i,j)=1 THEN block_init(n,45,r,g,b)
IF level(i,j)=2 THEN ! block_init(n,45,1,1,1) !white_blocks(n)=n !ENDIF
SPRITE n AT block_pos+((ball_size*2+1)*j), 100+block_init.y*i+((ball_size*2+1)*i)
SPRITE n SHOW
n+=1
ENDIF
NEXT j
r+=0.1 !g+=0.1!b-=0.1
NEXT i
1
data 0,1,1,1,1,1,1,0
data 1,1,1,1,1,1,1,1
data 0,1,1,1,1,1,1,0
data 1,1,1,1,1,1,1,1
data 9
2
data 1,1,1,0,0,1,1,1
data 0,1,1,1,1,1,1,0
data 1,1,1,1,1,1,1,1
data 1,1,1,0,0,1,1,1
data 9
3
data 0,1,1,1,1,1,1,0
data 1,1,1,1,1,1,1,1
data 0,1,1,1,1,1,1,0
data 1,2,2,1,1,2,2,1
Data 9
REFRESH ON
START:
OPTION SPRITE POS CENTRAL
SPRITE "kvadrat" AT w/2,h-40
SPRITE "krug" AT w/2, h-60
SPRITE "krug" SHOW
SPRITE "kvadrat" SHOW
RANDOMIZE
r=RND(1.0)
sdx=-0.25
sdy=-(1-ABS(sdx))
GET SPRITE "krug" POS kr_x,kr_y
t=0
IF TOUCH_X(0)>-1 THEN GOTO LOOP
GOTO START
LOOP:
GET SPRITE "kvadrat" POS kv_x,kv_y
GET SPRITE "krug" POS kr_x,kr_y
SPRITE "krug" AT sdx*speed+kr_x,sdy*speed+kr_y
IF kr_x-ball_size<=1 THEN ! sdx=ABS(sdx) ! SPRITE "krug" AT kr_x+(ball_size),kr_y ! wh=-1 !ENDIF 'слева
IF kr_x+ball_size>=w-1 AND sdx>0 THEN ! sdx=-sdx ! SPRITE "krug" AT kr_x-(ball_size),kr_y ! wh=-1 !ENDIF' справа
IF kr_y-ball_size<=1 AND sdy<0 THEN ! sdy=ABS(sdy) ! SPRITE "krug" AT kr_x,kr_y+(ball_size) !wh=-1 ! ENDIF
IF kr_y+20>=h THEN
life-=1!
IF life>=0 THEN ! lifes(life) ! PAUSE 2 ! GOTO START ! ELSE ! GOTO lose ! ENDIF
ENDIF
GET TOUCH 0 AS x,y
IF x>-1 THEN
IF t=0 THEN
x1=TOUCH_X(0)
GET SPRITE "kvadrat" POS kv_x1,kv_y1
ENDIF
delta=x-x1
IF kv_x1+(bat_wid/2)+delta>=w THEN
SPRITE "kvadrat" AT w-(bat_wid/2),kv_y1
ELSE
IF kv_x1-(bat_wid/2)+delta<=0 THEN
SPRITE "kvadrat" AT bat_wid/2,kv_y1
ELSE
SPRITE "kvadrat" AT kv_x1+delta,h-40
ENDIF ! ENDIF
t=1
ELSE
t=0
ENDIF
GET SPRITE "krug" POS kr_x,kr_y
GET SPRITE "kvadrat" POS kv_x,kv_y
IF kr_x+ball_size>=kv_x-bat_wid/2 AND kr_x-ball_size<=kv_x+bat_wid/2 AND kr_y+ball_size>=h-50 THEN
bat_wid_f=bat_wid+(ball_size*2)
point=bat_wid_f/2/6
IF kv_x>kr_x THEN ' если коллизия слева
LEFT = kv_x-(bat_wid_f/2)
left1 = LEFT+point
FOR i=1 TO 6
IF kr_x>=LEFT AND kr_x<left1 THEN sdx=(-0.6)+(i/10)
LEFT=LEFT+point
left1=left1+point
NEXT i
ENDIF
IF kv_x<kr_x THEN 'если коллизия справа
RIGHT=kv_x
right1=RIGHT+point
FOR i=1 TO 6
IF kr_x>=RIGHT AND kr_x<right1 THEN sdx=i/10-0.1
RIGHT=RIGHT+point
right1=right1+point
NEXT i
ENDIF
sdy=-(1-ABS(sdx))
SPRITE "krug" AT kr_x+(sdx*speed),kr_y+(sdy*speed)
k=0
wh=-1
ENDIF
FOR i=1 TO block_count
GET SPRITE i POS bl_x, bl_y
GET SPRITE "krug" POS kr_x, kr_y
bl_top=bl_y
bl_bottom=bl_y+block_init.y
bl_left=bl_x
bl_right=bl_x+bl_w
ball_top=kr_y-ball_size
ball_bottom=kr_y+ball_size
ball_left=kr_x-ball_size
ball_right=kr_x+ball_size
IF ball_right>=bl_left AND ball_left<=bl_right AND ball_top<=bl_bottom AND ball_bottom>=bl_top AND SPRITE_VISIBLE(STR$(i)) THEN
IF i<>white_blocks(i) THEN
bl+=1
s+=100
score(s)
SPRITE i HIDE
wh=0
ELSE
wh=1
ENDIF
IF kr_y>=bl_top AND kr_y<=bl_bottom THEN
sdx=-sdx
IF wh=1 THEN
wh=0
vonx=MIN(ABS(bl_right-ball_left),ABS(bl_left-ball_right))
IF sdx>0 THEN
SPRITE "krug" AT kr_x+vonx+(sdx*speed),kr_y+(sdy*speed)
ELSE
SPRITE "krug" AT kr_x-vonx+(sdx*speed),kr_y+(sdy*speed)
ENDIF
ENDIF
ELSE
sdy=-sdy
IF wh=1 THEN
wh=0
vony=MIN(ABS(bl_bottom-ball_top),ABS(bl_top-ball_bottom))
IF sdy>0 THEN
SPRITE "krug" AT kr_x+(sdx*speed),kr_y+vony+(sdy*speed)
ELSE
SPRITE "krug" AT kr_x+(sdx*speed),kr_y-vony+(sdy*speed)
ENDIF
ENDIF
ENDIF
IF bl=bl_max THEN ! level_number+=1 ! GOTO level_init! ENDIF
GOTO LOOP
ENDIF
NEXT i
GOTO LOOP
lose:
SPRITE "fg" SHOW
IF l<>1 THEN
SPRITE "lose" BEGIN bl_w*6, bl_w*6
SHADOW ON
DRAW FONT SIZE 70
DRAW TEXT "YOU LOSE" AT 0,bl_w
DRAW FONT SIZE 40!DRAW TEXT "Ваш счёт: "&s AT 0,bl_w+70
DRAW FONT SIZE 20
SPRITE END
SPRITE "lose" AT w/2,h/2
SPRITE "lose" SHOW
l=1
ENDIF
IF TOUCH_X(2)>-1 THEN ! SPRITE "fg" HIDE!SPRITE "lose" HIDE! l=0!
SPRITE "lose" BEGIN!GRAPHICS CLEAR!SPRITE "lose" END
GOTO restart! ENDIF
GOTO lose
Арканоид
- Mr. Kibernetik
- Site Admin
- Posts: 4786
- Joined: Mon Nov 19, 2012 10:16 pm
- My devices: iPhone, iPad, MacBook
- Location: Russia
- Flag:
Re: Ping Pong
Интересная программа.
Но я не думаю, что коллизию спрайтов стоит использовать для анализа столкновения с блоками.
Потому что коллизия спрайтов - это очень ресурсоемкий процесс, который включает в себя попиксельный анализ на перекрытие двух спрайтов.
Может быть анализ на попадание шарика в прямоугольники блоков будет работать быстрее.
Но я не думаю, что коллизию спрайтов стоит использовать для анализа столкновения с блоками.
Потому что коллизия спрайтов - это очень ресурсоемкий процесс, который включает в себя попиксельный анализ на перекрытие двух спрайтов.
Может быть анализ на попадание шарика в прямоугольники блоков будет работать быстрее.
Re: Ping Pong
А малое значение sprite delay может вызывать такие проблемы? У меня оно составляет всего 0.0015.Mr. Kibernetik wrote:Интересная программа.
Но я не думаю, что коллизию спрайтов стоит использовать для анализа столкновения с блоками.
Потому что коллизия спрайтов - это очень ресурсоемкий процесс, который включает в себя попиксельный анализ на перекрытие двух спрайтов.
Может быть анализ на попадание шарика в прямоугольники блоков будет работать быстрее.
Обойтись без коллизий пытался, и везде куда дотянулся обошелся другими средствами. С блоками пока по-другому не получается, буду думать.
- Mr. Kibernetik
- Site Admin
- Posts: 4786
- Joined: Mon Nov 19, 2012 10:16 pm
- My devices: iPhone, iPad, MacBook
- Location: Russia
- Flag:
Re: Ping Pong
Если вы знакомы с анимацией, то DELAY в данном случае - это частота кадров анимации спрайта.
В принципе fps 25 считается нормой чтобы не было явного моргания. Это соответствует DELAY 1/25.
Можете прикинуть, что сейчас вы анимируете спрайт 666 раз в секунду. Глаз столько не различает, а вот CPU - напрягается.
Соответственно при уменьшении частоты кадров величину покадрового смещения спрайта будет нужно увеличить (конечно пока он не проскакивает препятствие за один кадр).
В принципе fps 25 считается нормой чтобы не было явного моргания. Это соответствует DELAY 1/25.
Можете прикинуть, что сейчас вы анимируете спрайт 666 раз в секунду. Глаз столько не различает, а вот CPU - напрягается.
Соответственно при уменьшении частоты кадров величину покадрового смещения спрайта будет нужно увеличить (конечно пока он не проскакивает препятствие за один кадр).
- Mr. Kibernetik
- Site Admin
- Posts: 4786
- Joined: Mon Nov 19, 2012 10:16 pm
- My devices: iPhone, iPad, MacBook
- Location: Russia
- Flag:
Re: Ping Pong
Классическое название этой игры - арканоид.
- Фант
- Posts: 1363
- Joined: Sat Nov 30, 2013 10:01 am
- My devices: iPad 4 (iOS 9.3), iMac (MAC OS 11.03)
- Location: Россия,Санкт-Петербург
- Flag:
- Contact:
Re: Ping Pong
Привет! Я скажу что отличная программа! Классический арканоид. На айпад 4 все работает великолепно. Добавить выпадающие бонусы, добавить звук-будет готовый продукт.
Re: Ping Pong
В том-то и дело, что если существенно увеличить задержку, интервал смещения по вектору придется выставить слишком большой - оно приводит к регулярным косякам, взаимодействие спрайтов то и дело обрабатывается некорректно.Mr. Kibernetik wrote:Если вы знакомы с анимацией, то DELAY в данном случае - это частота кадров анимации спрайта.
В принципе fps 25 считается нормой чтобы не было явного моргания. Это соответствует DELAY 1/25.
Можете прикинуть, что сейчас вы анимируете спрайт 666 раз в секунду. Глаз столько не различает, а вот CPU - напрягается.
Соответственно при уменьшении частоты кадров величину покадрового смещения спрайта будет нужно увеличить (конечно пока он не проскакивает препятствие за один кадр).
Арканоид, точно
Re: Ping Pong
Спасибо за оценку и тестирование Разнообразие блоков и звуки в планах на будущее, наряду с таблицей рекордов и вменяемыми pop-up окнами победы и поражения.Фант wrote:Привет! Я скажу что отличная программа! Классический арканоид. На айпад 4 все работает великолепно. Добавить выпадающие бонусы, добавить звук-будет готовый продукт.
- Фант
- Posts: 1363
- Joined: Sat Nov 30, 2013 10:01 am
- My devices: iPad 4 (iOS 9.3), iMac (MAC OS 11.03)
- Location: Россия,Санкт-Петербург
- Flag:
- Contact:
Re: Ping Pong
Планка и мячик двигаются отлично-все работает четко. Мячик с блоками тоже работает как надо. Думаю есть шероховатости при пропуске мяча. Как то не внятно работает этот момент.
Re: Ping Pong
По задумке при пропуске мяча, то есть когда он достигает пола, игра ставится на 2-секундную паузу, а затем и доска, и мяч возвращаются в центр по своей оси X. На моем устройстве это работает именно так, а у вас как?Фант wrote:Думаю есть шероховатости при пропуске мяча. Как то не внятно работает этот момент.