@ПППППППППППППППП"юлюл лллллл юл юл юл юлююл юлююю ююллююююю ююююююлллюлллю лю лллллл ю ю юл юллл ю ю люлл лллюлл л юлллллл юлюлл лллл ююлллюллл лллл ю юю юю ю юллллююю юл юл ю ю ллл лллю ю л ллл юллллюлл л юлллллл юлюлл лллююлюл юлл л л ююл юл юл ллл лллюл лллллллллллюлл ллю юлллюлюллллллл лл л юл юлллллл л л лллл л л л л лллюллл л юл л л юл л л л л л ю л л юл юю юллюл юлю юл юл юллллллллюллллллллл лллллюллюллл л лл ллл л лл лллллллллллл лллюлллллллллллллллл лллююлююл ллююлююллллюлллллллюл юлл юллюллллллллллллл ллл юл лллллл ллллл юлллллллллллллллюллллллллллллллл юл л ю л юл лл ююлллллл юлллллллллюллюл юл л л ллв   2d,юллллллллл ллллллл юлллл юллллллллллллюллллллллл ллллллл юлллл юллллллллллллюллллллллл ллллллл юлллл юллллллллллллюллллллллл ллллллл юлллл юллллллллллллюллллллллл ллллллл юлллл юллллллллллллюлллл юллюлллл юллюлллллллюллюлллл юлллл юллюлллл юллюлллллллюллюлллл юлллл юллюлллл юллюлллллллюллюлллл юлллл юллюлллл юллюлллллллюллюлллл юлллл юллюлллл юллюлллллллюллюлллл юлллл юллюлллл юллюллллллллллллюлллл лллллюлллл юллюлллл юллюллллллллллллюлллл лллллюлллл юллюлллл юллюллллллллллллюлллл лллллюлллл юллюлллл юллюллллллллллллюлллл лллллюлллл юллюлллл юллюллллллллллллюлллл лллллюллллллллл юлллл юллюлллл лллллюлллл юллюллллллллл юлллл юллюлллл лллллюлллл юллюллллллллл юлллл юллюлллл лллллюлллл юллюллллллллл юлллл юллюлллл лллллюлллл юллюллллллллл юлллл юллюлллл лллллюлллл юллюлллл ллллллл юлллл юллллллллллллюлллл ллллллл юлллл юллллллллллллюлллл ллллллл юлллл юллллллллллллюлллл ллллллл юлллл юллллллллллллюлллл ллллллл юлллл юллллллллллллюл ю ю юл ю ю л юлю юлюл лл лллллл лл ю юллю ю лю л ю лл л л ю л л ю л л ю лл л л ю ю ллюлл юлюл л юл л ллюлл ю ллллллллллллллллллллллллллллллллллллллллллллллллллллл л лю юлю ю лююл ю ллюлюл ллюл л юллллл ллюлю юл л лю ю л л ю л ю лл л ю л л ю л люл юл л л ю л ю л л л ю лл ю л л юлю ллюлюл люл юлюлл л люлл лл юл лллллллллллллллллллллллллллллллллллллллллллллллллллл юл лю юлю ю ю л ллюл ллюлюл л юллллл ллюлю ю юлллюлл ю л лю ю лл л ю л л ю ю лю л л л ю лл ю л л л ю лл ю ю л лллл юл люлюл юлюлл л люлл л юллn-- title: PONG -- author: Zach Attakk -- desc: Basic implementation of PONG for the YouTube Tutorial -- site: https://bit.ly/pong_tutorial -- license: CC Attribution-NonCommercial (BY-NC 4.0) -- version: 0.13 -- script: lua -- menu: KEYBOARD CONTROLS SHARED CONTROLLER STATES = { GAMEPLAY = 0, WAIT_START = 1, START_MENU = 2 } -- GLOBALS PADDLE_HEIGHT = 16 BALL_SIZE = 4 GAME_SPEED = 1.0 STATE = STATES.START_MENU KEYBOARD = true ACTIVE_PLAYER = 1 MENU_ITEM = 0 PADDLES = { P1 = { id = 1, x = 2, y = 20, btn_up = 0, btn_dn = 1, btn_ok = 2, key_up = 1, key_dn = 26, key_ok = 24, speed = 1.2, prev_collide = false, last_move = -1, is_moving = false }, P2 = { id = 2, x = 234, y = 100, btn_up = 5, btn_dn = 4, btn_ok = 7, key_up = 58, key_dn = 59, key_ok = 60, speed = 1.2, prev_collide = false, last_move = -1, is_moving = false } } BALL = { -- 118, 62 x = 118, y = 62, dx = 1, dy = -1 } P1_SCORE = 0 P2_SCORE = 0 function BOOT() RESET() STATE = STATES.START_MENU end function RESET() if ACTIVE_PLAYER == 1 then BALL.x = PADDLES.P1.x + 4 +2 else BALL.x = PADDLES.P2.x - BALL_SIZE -2 end BALL.y = 62 GAME_SPEED = 1.0 STATE = STATES.WAIT_START end function TIC() INPUTS_GAME() if STATE == STATES.WAIT_START then INPUTS_START() UPDATES_START() elseif STATE == STATES.GAMEPLAY then UPDATES_GAME() end if (STATE == STATES.GAMEPLAY) or (STATE == STATES.WAIT_START) then DRAW_GAME() elseif STATE == STATES.START_MENU then INPUTS_MENU() DRAW_MENU() end if STATE == STATES.WAIT_START then DRAW_START() -- as an overlay end end -- TIC function INPUTS_MENU() if btnp(0) then MENU_ITEM = math.max(MENU_ITEM - 1, 0) sfx(1) elseif btnp(1) then MENU_ITEM = math.min(MENU_ITEM + 1, 1) sfx(1) end local confirm_buttons = {4,5,6,7} local confirm_keys = {48,50} for b = 1, #confirm_buttons do if btnp(confirm_buttons[b]) then MENU(MENU_ITEM) STATE = STATES.WAIT_START sfx(3) end end -- all the buttons for k = 1, #confirm_keys do if keyp(confirm_keys[k]) then MENU(MENU_ITEM) STATE = STATES.WAIT_START sfx(3) end end -- all the keys end -- inputs_menu function INPUTS_START() for i,pad in pairs(PADDLES) do if pad.id == ACTIVE_PLAYER then if (not KEYBOARD and btn(pad.btn_ok)) or (KEYBOARD and key(pad.key_ok)) then STATE = STATES.GAMEPLAY sfx(3) end -- do the thing end -- active controller end -- for each controller end -- inputs at start function INPUTS_GAME() -- Paddles up and down for i,pad in pairs(PADDLES) do pad.is_moving = false if (not KEYBOARD and btn(pad.btn_up)) or (KEYBOARD and key(pad.key_up)) then --move paddle up pad.y = pad.y-(pad.speed*GAME_SPEED) pad.last_move = -1 pad.is_moving = true end if (not KEYBOARD and btn(pad.btn_dn)) or (KEYBOARD and key(pad.key_dn)) then pad.y = pad.y+(pad.speed*GAME_SPEED) pad.last_move = 1 pad.is_moving = true end -- paddle up/down end -- check whether paddles have left the screen for i,pad in pairs(PADDLES) do if pad.y < 1 then -- we've gone past the top of the screen pad.y = 1 elseif pad.y+PADDLE_HEIGHT > 135 then pad.y = 135-PADDLE_HEIGHT end end -- all paddles end -- INPUTS function UPDATES_START() if ACTIVE_PLAYER == 1 then BALL.y = PADDLES.P1.y+(PADDLE_HEIGHT/2)-(BALL_SIZE/2) BALL.dy = PADDLES.P1.last_move else BALL.y = PADDLES.P2.y+(PADDLE_HEIGHT/2)-(BALL_SIZE/2) BALL.dy = PADDLES.P2.last_move end end function UPDATES_GAME() -- move the ball BALL.x = BALL.x + (BALL.dx*GAME_SPEED) BALL.y = BALL.y + (BALL.dy*GAME_SPEED) -- ball edge bounces if (BALL.y < 1) or (BALL.y + BALL_SIZE > 135) then BALL.dy = 0 - BALL.dy sfx(0) end -- ball to paddle for i,pad in pairs(PADDLES) do local pad_collide = check_ball_collision(pad) if pad_collide and not pad.prev_collide then pad_hit(pad) end pad.prev_collide = pad_collide end -- for each paddle -- score if BALL.x > 240 then P1_SCORE = P1_SCORE +1 sfx(2) ACTIVE_PLAYER = 1 RESET() elseif BALL.x + BALL_SIZE < 0 then P2_SCORE = P2_SCORE +1 sfx(2) ACTIVE_PLAYER = 2 RESET() end end -- UPDATES function DRAW_GAME() cls() --boundaries line(0, 0, 240, 0, 14) line(0, 135, 240, 135, 14) -- net for _i=2,136,8 do rect(119, _i, 2, 4, 14) end -- paddles for i,pad in pairs(PADDLES) do rect(pad.x, pad.y, 4, PADDLE_HEIGHT, 12) end -- ball rect(BALL.x, BALL.y, BALL_SIZE, BALL_SIZE, 12) end -- DRAW GAME function DRAW_START() -- print ready print_center("READY", 80, 2) local arrow_flip = 0 if BALL.dy > 0 then arrow_flip = 2 end if ACTIVE_PLAYER == 1 then print_center("PLAYER 1", 94, 1) spr(272, BALL.x-2, BALL.y-2, 0, 1, arrow_flip) else print_center("PLAYER 2", 94, 1) spr(272, BALL.x-2, BALL.y-2, 0, 1, arrow_flip+1) end -- score -- print_center(txt, y_pos, scale, x_offset) print_center(P1_SCORE, 40, 4, -60) print_center(P2_SCORE, 40, 4, 60) -- controls if KEYBOARD then spr(322, 30, 100, 0, 1, 0, 0, 4,4) spr(326, 240-30-32, 100, 0, 1, 0, 0, 4,4) else spr(258, 30, 100, 0, 1, 0, 0, 4,4) spr(262, 240-30-32, 100, 0, 1, 0, 0, 4,4) end end -- draw start function DRAW_MENU() cls(0) print_center("PONG", 30, 5) print_center("Select Input:",70) print_center("Keyboard Controls",80) print_center("Shared Controller",90) -- draw selection rectb(68,78+(MENU_ITEM*10), 105, 10, 12) end -- HELPERS function MENU(id) if id == 0 then -- keyboard controls KEYBOARD = true elseif id == 1 then -- controller controls KEYBOARD = false end end function check_ball_collision(pad) if (BALL.x < pad.x+4) and (BALL.x+BALL_SIZE > pad.x) and (BALL.y < pad.y+PADDLE_HEIGHT) and (BALL.y+BALL_SIZE > pad.y) then return true end return false end -- ball collision function pad_hit(pad) BALL.dx = 0-BALL.dx if pad.is_moving then BALL.dy = clamp(BALL.dy + (pad.last_move * 0.5), -2, 2) end sfx(1) if GAME_SPEED < 4 then GAME_SPEED = GAME_SPEED + 0.2 end end function clamp(val, min_val, max_val) local lower = math.min(val, max_val) return math.max(lower, min_val) end function print_center(txt, y_pos, scale, x_offset) -- make scale optional if scale == nil then scale = 1 end -- make x_offset optional if x_offset == nil then x_offset = 0 end local length = print(txt, 0, -200, 12,true, scale) print(txt, 121-(length/2)+x_offset, y_pos, 12,true, scale) end