6
\$\begingroup\$

This simple game is built on the ECS described here: Minimal entity component system, take 2

local ecs = require 'ecs'
local ui = require 'ui'
local entities = {}
local velocitySystem = ecs.createSystem(
 { 'position', 'velocity' },
 function (entity, pos, vel)
 pos.x = pos.x + vel.vx
 pos.y = pos.y + vel.vy
 end)
local rectangleRenderingSystem = ecs.createSystem(
 { 'position', 'rectangle' },
 function (entity, pos, rect)
 ui.drawRect(pos, rect)
 end)
local aiSystem = ecs.createSystem(
 { 'position', 'speed', 'ai' },
 function (entity, pos, speed)
 local closestBallPos
 for target, posB in ecs.each(entities, { 'position', 'ball' }) do
 if (not closestBallPos) or (posB.x > closestBallPos.x) then
 closestBallPos = posB
 end
 end
 pos.y = pos.y + (closestBallPos.y - pos.y) * speed
 end)
local inputSystem = ecs.createSystem(
 { 'position', 'player' },
 function (entity, pos)
 pos.y = ui.mouseY or 0
 end)
local outOfBoundsSystem = ecs.createSystem(
 { 'position', 'rectangle', 'velocity', 'ball' },
 function (entity, pos, rect, vel)
 if pos.x <= 0 then
 print('Right player scored')
 pos.x = 50
 elseif pos.x >= 100 then
 print('Left player scored')
 pos.x = 50
 end
 end)
local bounceSystem = ecs.createSystem(
 { 'position', 'rectangle', 'velocity', 'ball' },
 function (entity, pos, rect, vel)
 if pos.y <= 0 or pos.y >= 100 then
 vel.vy = vel.vy * -1
 end
 end)
local function checkCollision(posA, rectA, posB, rectB)
 local halfHeightA, halfHeightB = rectA.h / 2, rectB.h / 2
 local halfWidthA, halfWidthB = rectA.w / 2, rectB.w / 2
 if (posA.y + halfHeightA <= posB.y - halfHeightB) or 
 (posA.y - halfHeightA >= posB.y + halfHeightB) or
 (posA.x + halfWidthA <= posB.x - halfWidthB) or 
 (posA.x - halfWidthA >= posB.x + halfWidthB) then
 return false
 end
 return true
end
local collisionSystem = ecs.createSystem(
 { 'collidable', 'position', 'rectangle', 'velocity' },
 function (entity, col, pos, rect, vel)
 for target, posB, rectB in ecs.each(entities,
 { 'position', 'rectangle', 'solid' }) do
 if entity == target then next() end
 if checkCollision(pos, rect, posB, rectB) then
 vel.vx = vel.vx * -1
 vel.vy = vel.vy * -1
 end
 end
 end)
local ball = {
 ball = true,
 collidable = true,
 position = { x = 50, y = 33 },
 velocity = { vx = 1, vy = 1 },
 rectangle = { w = 2, h = 2 },
}
local leftPaddle = {
 player = true,
 solid = true,
 position = { x = 0, y = 50 },
 rectangle = { w = 4, h = 10 },
}
local rightPaddle = {
 ai = true,
 solid = true,
 speed = 0.5,
 position = { x = 100, y = 50 },
 rectangle = { w = 4, h = 10 },
}
table.insert(entities, ball)
table.insert(entities, leftPaddle)
table.insert(entities, rightPaddle)
ui.loop(function ()
 velocitySystem(entities)
 rectangleRenderingSystem(entities)
 aiSystem(entities)
 inputSystem(entities)
 outOfBoundsSystem(entities)
 bounceSystem(entities)
 collisionSystem(entities)
end)

I'm wondering if I have the right idea about how I should be using an ECS. If there are problems with the ECS itself, please address it in linked question rather than here.

The "ui" script that's required at the top is some uninteresting OpenGL/GLUT stuff using luaglut. I can post it if necessary, but it should be pretty clear what it's doing.

I realize there are lots of magic numbers. I don't care, it's just a throwaway project to make sure the ECS is doing its job. All of the coordinates and measurements are in percents, so just pretend I made constants named FIFTY_PERCENT and so on.

asked Aug 31, 2014 at 16:52
\$\endgroup\$

0

Know someone who can answer? Share a link to this question via email, Twitter, or Facebook.

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.