This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
billysback's profile picture

[API] CGE - Computercraft Game Engine [v1.2] - Colors!

Started by billysback, 08 October 2012 - 08:29 PM
billysback #1
Posted 08 October 2012 - 10:29 PM

CGE is ComputerCraft Game Engine it is an API which can vastly reduce the amount of code needed to made a mini game (or other applications) and simplify the code needed. It does not do lots currently but I hope for it to grow, with hopefully the communities help. So for this reason I ask you to please reply to say either what you think of it, what your first impressions are, a suggestion for it or anything of that sort. Thank you.

Functions:
SpoilerconstructMap(map)
returns a formatted version of the map you gave which CGE can read and use,
so you would input something like {"+++","+++","+++"} and CGE would read a 3x3
cube made out of the "+" symbol only

constuctSprite(sx, sy, sprite, name, maxani)
returns a formatted version of the sprite you gave which CGE can read and use,
so you would input something like {"#","##"} and CGE would read a 2x2 L shape
made out of the "#" symbol only
sx and sy are the starting x/y coordinates of the sprite (the upper left hand corner)
name is the name of the sprite
maxani is the maximum frame of animation that the sprite has; set to 1 if left as nil.


createSprite(xtable, ytable, ttable, name, maxani)
returns a formatted version of the sprite you gave which CGE can read and use,
so you would input something like {0,0,1}{0,1,1}{"#","#","#"} and CGE would read a 2x2 L shape
made out of the "#" symbol only, exactly the same as the constructSprite example
name is the name of the sprite
maxani is the maximum frame of animation that the sprite has; set to 1 if left as nil.

changeSprite(sprite, nsprite)
if sprite is found in the games sprite list then it is replaced with nsprite.
sprite is the original sprite
nsprite is the replacement sprite

addSprite(sprite)
adds the chosen sprite in to the game

deleteSprite(sprite)
deletes the chosen sprite from the game

getSprite(name)
returns the first sprite found with that name

getSprites()
returns a table containing all sprites currently in the game

addSprites(sprites)
adds that list of sprites to the game.

setSprites(sprites)
sets the table containing all the sprites in the game to this new table

getMap()
returns the current map

setMap(map)
sets the map currently being used by the game to the chosen one

setMapLoc(x, y, type)
sets the character at the x, y position on the map to the character chosen (type)
type is the character chosen to replace the one found at the x, y coordinate

moveSprite(sprite, dirx, diry, smart)
returns a new sprite which is the same as the one chosen in the function but has
been moved along the x coordinate by dirx and along the y coordinate by diry
smart is true/false value, if true then the sprite is only moved when it did not collide after movement

checkCollision(sprite, sprites)
returns true/false depending on whether it detected a collision between any of the sprites
in the sprites table and the sprite you chose, ignoring the sprite you chose if it happens
to be in the sprites table

setVelocity(sprite, dir, momentum)
this sets the velocity of the sprite in question
sprite is the sprite having it's velocity set.
dir is the direction of the velocity as a table containing {x,y}, x and y can be any integer
momentum is the force it travels at, if this is greater than zero then the sprite moves when
the velocity is updated.

getVelocity(sprite)
returns the velocity in the format:
"momentum,dirx,diry"

updateVelocity(sprite, resistance, smart)
this updates the velocity of the sprite.
resistance is the amount taken away from the momentum (if the momentum is >0)
smart works the same way as it does in moveSprite()

getCurAnimation(sprite)
gets the current animation frame of the sprite.
sprite is the sprite in question

animateSprite(sprite, forwards)
this loops through the sprites animation frames, moving one back or forwards every call depending
on whether the forwards variable is equals to true or false
sprite is the sprite being animated
forwards is whether or not the animation is scrolling through it's frames forwards or backwards

animateSprites(sprites, forwards)
does the same as animateSprite() but animates every sprite in the 'sprites' table variable, so that
you can easily animate multiple sprites at once.

setSpriteAnimationFrame(sprite, frame)
sets the current animation from of the sprite in question to the frame, if out of frame boundaries then it
is set to the highest/lowest frame boundry, which ever is relevant.
sprite is the sprite having its animation frame edited
frame is the number frame that you are switching to.

getSpriteCode(sprite)
returns a single string containing all information on this sprite
sprite is the sprite being encoded

readSpriteCode(code)
returns a sprite based on the code given
code is the encoded version of the sprite

readSprite(sx, sy, dir, name, maxani, colored)
this returns a sprite created by reading the defined file
sx is the starting x coordinate for the sprite
sy is the starting y coordinate for the sprite
dir is the directory for the sprite to be read from
maxani is the max animation frame (kinda irrelavant for this)
colored is whether or not the file is reading a sprite made of colors or of strings

readAnimatedSprite(sx, sy, dirs, name, maxani, colored)
this is exactly the same as readSprite() however it returns a sprite
with an animation, the only variable difference is:
dirs is a table containing all directors to be read as animation frames, in order of frame 1 to tablesize.

readMap(dir)
returns a map read from a file

addGravity(x, y, force)
adds a gravitational center
x is the x coordinate for the gravitational center
y is the y coordinate for the gravitational center
force is the force (range) for the gravitation center, force uses the formula:
(x + y)/2 = f, where x, y are the coordinates of a sprite and f is the required force

removeGravity(grav)
removes this gravitational center

removeGravity(x, y, force)
removes any gravitational center which has those x, y, and force values.

getGravityPoints()
returns a table containing all gravitiation centers

updateGravity(sprite, smart)
updates the sprite so it is affected by gravity (as long as it's in range of a gravitational center)
sprite is the sprite being updated
smart is whether or not smart movement is allowed (checks for collisions)

getSpriteBounds(sprite)
returns a table containing the x,y coordinates of upper left and lower right corners of the box surrounding the sprite
(an imaginary box)
sprite is the sprite having its bounds taken

flipSprite(sprite, flipx, flipy)
flips the sprite along the chosen axis.
sprite is the sprite being flipped
flipx is true/false depending on whether you want to flip along the x axis
flipy is true/false depending on whether you want to flip along the y axis

colorDraw(offx, offy)
does the exact same as draw() but also checks to see if the sprite is using color tags,
if so then it will color the sprite in the correct colors, if not it will act as normal
(credit to marumaru for the setPixel and getColor functions!)

draw(offx, offy)
draws the current game, offset by the x and y coordinates (the position of every x and y coordinate
is changed by the offx and offy)

Heres a paste of CGE:
Spoilerhttp://pastebin.com/r2UReK1M

Heres a download:
Spoilerv1.0 - [attachment=530:cge.zip]
v1.1 - [attachment=539:cge.zip]
v1.2 - [attachment=553:cge.zip]

Heres an example program paste:
Spoilerhttp://pastebin.com/TwUAkG0g

Heres a tutorial (v1.1)
SpoilerCGE Tutorial:

This is a tutorial which will guide you through using GME and all it's functions, I recommened downloading the programs Notepad++ and
CCEmulater in order to code and test your programs easier before starting this tutorial, if you wish, however, you can use your computer
the tutorial will not rely on using any form of coding your program.

To start, make a new program called "pacman"
(note some of the allignment of the code is messed up, however the code still works and should be understandable.)

Step 1: Making a map
SpoilerYou should have nothing but an empty screen when you start programming your program, if not delete everything thats on it (or start a new
program) before starting this tutorial…

Now, our map could be whatever we want it to be, but for our program we want it to be blank with a border.
To make a map you need to make a new table, lets call our table "map",

local map = {}
now we need to define the map, the map is a table (as I previously stated) and inside the table is what the map (or background) will look
like, each line is one line of the map. If that makes sense, if not look at the code and figure it out (or ask if you still don't understand)

local map = {"+-----------+",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "+-----------+"}

So thats our map it should be pretty obvious what that outputs…
now we need to quickly use the contstructMap function to put it in to CGE format:

local map = {"+-----------+",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "+-----------+"}
local cgemap = cge.constructMap(map)

we also need to add the map in to the game, so to do that we just use the setMap function, very simple:

local map = {"+-----------+",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "+-----------+"}
local cgemap = cge.constructMap(map)
cge.setMap(cgemap)
the function should be easy to understand what it does.


Step 2: Making a sprite
SpoilerIn the latest update our sprites can be animate, so lets take advantage of this and create our animated packman:
lets make a function which creates a 2 frame animated sprite and call it "makeSprite", so fist create the function

local function makeSprite()

end

now we want a few variables in the makeSprite() parenthesis, those are:
sx - the starting x coordinate of the sprite
sy - the starting y coordinate of the sprite
name - the name of the sprite
c - a table containing all of the frames of the animations

so lets add these in:

local function makeSprite(sx, sy, name, c)

end

now we want to turn all of the characters in c in to one string, each character being split up but a ',', so lets add a table
loop to loop through all of the characters and add them to a string (called type)
we also want to get the size of c, so lets throw in another variable called sz which we will set to i on every loop


local function makeSprite(sx, sy, name, c)
	local type = ""
	local sz = 0
	for i,v in ipairs(c) do
		if i == 1 then
			type = v
		else
			type = type..","..v
		end
		sz = i
	end
end

type is the type of string that every string in the sprite is going to be, for each frame.
sz is the size of the c table, I will explain why this is needed a little bit later

now we need to make our x,y,t tables to create (not construct, that doesn't support animations as well) our sprite.
these are going to be rather simple as our sprite is only 1x1 large, so lets quickly create those


local function makeSprite(sx, sy, name, c)
	local type = ""
	local sz = 0
	for i,v in ipairs(c) do
		if i == 1 then
			type = v
		else
			type = type..","..v
		end
		sz = i
	end

	local xsprite = { sx }
	local ysprite = { sy }
	local tsprite = {type}
end

now we are ready to create our sprite and then add it to the game, for this we are going to use two CGE
functions,
createSprite(xsprite, ysprite, tsprite, name, maxani)
addSprite(sprite)
(look them up in functions to see what they do if you are unsure of what they do)

as you can see, maxani is required for this function (maximum animation frame), this is where we are going
to use the size of c, as the size of c must equal the amount of frames.
so lets quickly define a new variable as sprite and set it to equal createSprite with our variables plugged in

local function makeSprite(sx, sy, name, c)
	local type = ""
	local sz = 0
	for i,v in ipairs(c) do
		if i == 1 then
			type = v
		else
			type = type..","..v
		end
		sz = i
	end

	local xsprite = { sx }
	local ysprite = { sy }
	local tsprite = {type}
	local sprite = cge.createSprite(xsprite, ysprite, tsprite, name, sz)
end

now that we have created our sprite we need to add it in to the game, otherwise it won't be drawn…
so for that we just add in our second function, which only requires one variable, sprite.

local function makeSprite(sx, sy, name, c)
	local type = ""
	local sz = 0
	for i,v in ipairs(c) do
		if i == 1 then
			type = v
		else
			type = type..","..v
		end
		sz = i
	end

	local xsprite = { sx }
	local ysprite = { sy }
	local tsprite = {type}
	local sprite = cge.createSprite(xsprite, ysprite, tsprite, name, sz)
	cge.addSprite(sprite)
	return sprite
end
this function also returns the sprite we have created, just in case.

and thats it, when you call this function with the correct variable it will automatically create your sprite
for you!


Step 3: creating the walls
SpoilerThe walls that pacman is going to collide with must be a sprite, so that we can easily use the "checkCollision" function in CGE.
however, as the sprite doesnt need to be animated and is going to be large we can just use constructSprite for this one and create it
in a very similar way to how we created out map.

so first lets initiate a new variable called "prewalls" which will be a table

prewalls = {}

now lets create a blank square which is the same size as the map but -2 in both dimensions (to fit inside the walls

local prewalls = {"		   ",
				  "		   ",
				  "		   ",
				  "		   ",
				  "		   ",
				  "		   ",}

now we need to design our walls, we are going to use the 'X' charcter as the character for out walls, so lets first surround the whole
with X

local prewalls = {"XXXXXXXXXXX",
				  "X		 X",
				  "X		 X",
				  "X		 X",
				  "X		 X",
				  "XXXXXXXXXXX",}

now we can fill the insides however we want, I'll give an example here but feel free to design your walls however you want (you can also
make the map bigger if you wish, though you will need to understand the implications it will have on things I will be going through later,
like placing pacman)


local prewalls = {"XXXXXXXXXXX",
				  "X   X	 X",
				  "X X   X X X",
				  "X X X   X X",
				  "X	 X   X",
				  "XXXXXXXXXXX",}

Now we need to create our sprite using the construct method, we will call the sprite "walls" for both its name and variable:
we are also going to make it start at x=1, y=1 so that it is inside the map, as we designed it to do so. the maxani is going to be
1 as there is no animation

local prewalls = {"XXXXXXXXXXX",
				  "X   X	 X",
				  "X X   X X X",
				  "X X X   X X",
				  "X	 X   X",
				  "XXXXXXXXXXX",}
local walls = cge.constructSprite(1, 1, prewalls, "walls", 1)

now lets quickly throw in the addSprite method to add it to the game as well.

local prewalls = {"XXXXXXXXXXX",
				  "X   X	 X",
				  "X X   X X X",
				  "X X X   X X",
				  "X	 X   X",
				  "XXXXXXXXXXX",}
local walls = cge.constructSprite(1, 1, prewalls, "walls", 1)
cge.addSprite(walls)

and we are done! the walls are added in to the game and will obstruct pacman when we get round to making him.


Part 4: creating pacman
SpoilerFirstly, lets create pacman using our previously set makeSprite function;
pacmans location will be x=8, y=3 as our map is 13 wide so to put him in the middle x must equal 8 and y=3 moves him down enough so that
he is not hitting anything, his characters will be
"@" and "O" and his name will be "pacman".

local pacman = makeSprite(8, 3, "pacman", {"@","O"}

thats it, I couldn't really think of anything which should go along side this part so it just shows how simply making a sprite is.

However before we move on to part 5, which start to make the game actually run, we should take a look at where we should be.
Please actually complete the tutorial instead of copying this code though:
Spoiler

local function makeSprite(sx, sy, name, c)
	local type = ""
	local sz = 0
	for i,v in ipairs(c) do
		if i == 1 then
			type = v
		else
			type = type..","..v
		end
		sz = i
	end

	local xsprite = { sx }
	local ysprite = { sy }
	local tsprite = {type}
	local sprite = cge.createSprite(xsprite, ysprite, tsprite, name, sz)
	cge.addSprite(sprite)
	return sprite
end

local map = {"+-----------+",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "+-----------+"}
local cgemap = cge.constructMap(map)
cge.setMap(cgemap)

local prewalls = {"XXXXXXXXXXX",
				  "X   X	 X",
				  "X X   X X X",
				  "X X X   X X",
				  "X	 X   X",
				  "XXXXXXXXXXX",}
local walls = cge.constructSprite(1, 1, prewalls, "walls", 1)
cge.addSprite(walls)

local pacman = makeSprite(8, 3, "pacman", {"@","O"}
Check your code against this, make sure you have gone through everything correctly!


Part 5: creating a game loop
SpoilerThis part actually has nothing to do with CGE, but it is essential in making almosty any game or application which runs of a similar basis.

At the bottom of the code we first want to initialize our timer and our on boolean check (as varibles don't have names in Lua you may not know what a boolean is,
a boolean is a variable which can only have one of two possible values, in most cases it is true or false instead of a logical 0 or 1)
so lets create our 2 variables:

local on = true
local timer = os.startTimer(0)
the use of the on variable will be explained a little bit later, the use of the timer varibale is to notify the game every time it should update.

At first the timer is set to 0 so that there is little delay between starting up the program and the game starting, however we do want an interval between updates,
however only something small. For pacman 0.5 seconds should be adequet, so lets create a new variable called 'interval' which is defined as 0.5 so that it is easy
to use and change our interval time.

local on = true
local timer = os.startTimer(0)

local interval = 0.5

Now we need to start our while loop, our while loop is going to check every time to see if on = true, if it is false then it will stop the loop and the game will
stop, this is so that we can add an escape function for if the user wishes to quit the game.

So lets start our while loop:

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do

end

Inside the while loop we want to use os.pullEvent, this checks for events being triggered to do with the computer, if you don't fully understand what I'm defining
and doing with the function and the variables I am initializing out of it look at this CC wiki article:
http://computercraft...le=Os.pullEvent
or look at this tutorial which explains a bit about os.pullEvent and what it is usually used for
http://www.computerc...__fromsearch__1

so now lets get our event:

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
	local event, p1, p2 = os.pullEvent()
end

now we want to checks, we want to check is event is equals to the string "timer" (and if p1 is to the variable "timer") and we want a second elseif check
to check if the event is equal to the string "key".
So lets add this if + elseif statement in underneith the os.pullEvent()

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
	local event, p1, p2 = os.pullEvent()
	if event == "timer" and p1 == timer then

	elseif event == "key" then

	end
end

now inside the timer if statement we need to start by doing one thing; reset the timer.
this time we will be using the interval variable we set earlier and doing almost an identical line to how we initiated the timer.
So lets add this line in:

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
	local event, p1, p2 = os.pullEvent()
	if event == "timer" and p1 == timer then
		timer = os.startTimer(interval)
		
	elseif event == "key" then

	end
end

this is the end of the game loop part, it continues with the same code in the next part.

Part 6: updating the game
Spoilernow we need to draw and update the game every time the timer is called, so first lets start of with clearing the console and
setting the cursor position to 1,1, these functions should be known to anyone with adequet enough knowledge of CC to be following
this tutorial…

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
	local event, p1, p2 = os.pullEvent()
	if event == "timer" and p1 == timer then
		timer = os.startTimer(interval)
		term.clear()
		term.setCursorPos(1,1)
	elseif event == "key" then

	end
end

so thats simple enough, now we want to draw our map, so lets add in the cge draw function, this is very simple and doesn't
really need much explanation:

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
	local event, p1, p2 = os.pullEvent()
	if event == "timer" and p1 == timer then
		timer = os.startTimer(interval)
		term.clear()
		term.setCursorPos(1,1)
		cge.draw(1,1)
	elseif event == "key" then

	end
end
the 1,1 offset the map by x=1 and y=1, this means when drawing both map and sprites all x values have 1 added on to them and
all y values have 1 added on to them, these could be 0 or any other number you chose to put in them.

now we want to update two things for our pacman; the pacman's animation and the pacman's velocity.
lets start with the animation, this is very simple:

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
	local event, p1, p2 = os.pullEvent()
	if event == "timer" and p1 == timer then
		timer = os.startTimer(interval)
		term.clear()
		term.setCursorPos(1,1)
		cge.draw(1,1)
		cge.animateSprite(pacman, true)
	elseif event == "key" then

	end
end
pacman is the sprite we are updating, true is whether you are moving the animation forwards or backwards, true is
for forwards, false is for backwards.
if animating multiple sprites at once you can use cge.animateSprites(sprites, true/false)
this is exactly the same apart from sprites is a table containing all of the sprites you wish to update, to do this
with all sprites in the game you can do:
cge.animateSprites(cge.getSprites(), true/false)

cge.animateSprite() does return a new sprite, however we do not need to use this new sprite as it also updates the
sprite for us.

now, we want to update pacman's velocity.
we will use the smart movement feature on the updateVelocity function so that we don't have to deal with it colliding with our only
other sprites, walls, however if we make it more complex and add things like ghosts, fruits and coins in to the game then we would
have to check the collisions our self as smart wouldn't work.

so lets add in our updateVelocity function then I will explain what it does.

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
	local event, p1, p2 = os.pullEvent()
	if event == "timer" and p1 == timer then
		timer = os.startTimer(interval)
		term.clear()
		term.setCursorPos(1,1)
		cge.draw(1,1)
		cge.animateSprite(pacman, true)
		local npacman = cge.updateVelocity(npacman, 0, true)
	elseif event == "key" then

	end
end
pacman is our sprite, this is the sprite which is having it's velocity updated.
0 is our resistance, our momentum is taken away by this everytime the velocity is updated.0 means it carries on moving forwards until
I change it manually.
true means smart movement is on, this means that if it collides with another sprite when it moves it returns it to it's original position.

we created a new variable called 'npacman' which is the updated version of pacman
now we need to change the original pacman to this updated version of pacman.
To do this we use the function: changeSprite()
so lets add this in and then I will explain what it does.

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
	local event, p1, p2 = os.pullEvent()
	if event == "timer" and p1 == timer then
		timer = os.startTimer(interval)
		term.clear()
		term.setCursorPos(1,1)
		cge.draw(1,1)
		cge.animateSprite(pacman, true)
		local npacman = cge.updateVelocity(npacman, 0, true)
		cge.changeSprite(pacman, npacman)
	elseif event == "key" then

	end
end
pacman is the original sprite which it will look for when looking through the game's sprites,
npacman is the the sprite that will replace the original sprite if it is found in the game's sprites

we also need to refresh our pacman sprite every loop,
so we use the getSprite() function to get a sprite by its name.
Lets add that in at the end of our loop, and also whenever the timer is called (this helps stop bugs occurring):

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
	local event, p1, p2 = os.pullEvent()
	if event == "timer" and p1 == timer then
		pacman = cge.getSprite("pacman")
		timer = os.startTimer(interval)
		term.clear()
		term.setCursorPos(1,1)
		cge.draw(1,1)
		local npacman = cge.animateSprite(pacman, true)
		npacman = cge.updateVelocity(npacman, 0, true)
		cge.changeSprite(pacman, npacman)
	elseif event == "key" then

	end
	pacman = cge.getSprite("pacman")
end

now that sit, the has drawn and updated itself and will continue to do so every 0.5 seconds as long as on = true.

Part 7: adding controls
SpoilerThis is the final part of our basic pacman game, we will be using the second if statement to add controls for our pacman.
The first thing we need to do is define our key as p1, so lets do that:
(I will only be using this if statement this time, to save space)

	elseif event == "key" then
		local key = p1
	end

now we want to add a check for 5 different keys, up arrow, left arrow, right arrow, down arrow and escape.
You can look these up using this mincraft wiki page: http://www.minecraft.../wiki/Key_Codes

so to check if a key is a certain keycode you simply do
if key == keycode then,
so lets add all 5 of our checks in strait away:

	elseif event == "key" then
		local key = p1
		if key == 1 then --escape key

		elseif key == 200 then --up arrow key

		elseif key == 208 then --down arrow key

		elseif key == 203 then --left arrow key

		elseif key == 205 then --right arrow key

		end
	end

now in the escape key section all we need to add is on = false
this will imidiatly stop the game as it will stop the while loop.
Lets add that in:

	elseif event == "key" then
		local key = p1
		if key == 1 then --escape key
			on = false
		elseif key == 200 then --up arrow key

		elseif key == 208 then --down arrow key

		elseif key == 203 then --left arrow key

		elseif key == 205 then --right arrow key

		end
	end

now for all of the other keys we need to set pacmans velocity, this is a simple function that I will go through
now then add in to all 4 at once.
the function is:
setVelocity(sprite, dir, momentum)
sprite is the sprite in question
dir is a table containing only {x,y}, this is the amount that the sprite will move in the x direction and the
amount that the sprite will move in the y direction.
momentum is the momentum it has, this is irrrelivant for us as we do not have resistance, as long as it is above 0
then we can set it to whatever number we want.

the function returns a newsprite so we will have to again change the sprite in the game using changeSprite().

so lets add those in.

	elseif event == "key" then
		local key = p1
		if key == 1 then --escape key
			on = false
		elseif key == 200 then --up arrow key
			local npacman = cge.setVelocity(pacman, {0,-1}, 1)
			cge.changeSprite(pacman, npacman)
		elseif key == 208 then --down arrow key
			local npacman = cge.setVelocity(pacman, {0,1}, 1)
			cge.changeSprite(pacman, npacman)
		elseif key == 203 then --left arrow key
			local npacman = cge.setVelocity(pacman, {-1,0}, 1)
			cge.changeSprite(pacman, npacman)
		elseif key == 205 then --right arrow key
			local npacman = cge.setVelocity(pacman, {1,0}, 1)
			cge.changeSprite(pacman, npacman)
		end
	end
the only thing that changes in each of these is the x,y values, making it move in the direction that you chose
using your arrow keys.


and thats it for your controls.

We have finished our basic pacman game now, all we need to do is put all of the code together and add two extra line
to the bottom of the code:

term.clear()
term.setCursorPos(1,1)
this will reset the screen once the game is quit.

So here is the finished code,
please do not just copy this if you are following the tutorial as it will not help you nearly as much as following the tutorial will:
Spoiler

local function makeSprite(sx, sy, name, c)
		local type = ""
		local sz = 0
		for i,v in ipairs(c) do
				if i == 1 then
						type = v
				else
						type = type..","..v
				end
				sz = i
		end

		local xsprite = { sx }
		local ysprite = { sy }
		local tsprite = {type}
		local sprite = cge.createSprite(xsprite, ysprite, tsprite, name, sz)
		cge.addSprite(sprite)
		return sprite
end

local map = {"+-----------+",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "|		   |",
			 "+-----------+"}
local cgemap = cge.constructMap(map)
cge.setMap(cgemap)

local prewalls = {"XXXXXXXXXXX",
				  "X   X	 X",
				  "X X   X X X",
				  "X X X   X X",
				  "X	 X   X",
				  "XXXXXXXXXXX",}
local walls = cge.constructSprite(1, 1, prewalls, "walls", 1)
cge.addSprite(walls)

local pacman = makeSprite(8, 3, "pacman", {"@","O"})

local on = true
local timer = os.startTimer(0)

local interval = 0.5

while on do
		local event, p1, p2 = os.pullEvent()
		if event == "timer" and p1 == timer then
				pacman = cge.getSprite("pacman")
				timer = os.startTimer(interval)
				term.clear()
				term.setCursorPos(1,1)
				cge.draw(1,1)
				cge.animateSprite(pacman, true)
				local npacman = cge.updateVelocity(pacman, 0, true)
				cge.changeSprite(pacman, npacman)
		elseif event == "key" then
				local key = p1
				if key == 1 then --escape key
						on = false
				elseif key == 200 then --up arrow key
						local npacman = cge.setVelocity(pacman, {0,-1}, 1)
						cge.changeSprite(pacman, npacman)
				elseif key == 208 then --down arrow key
						local npacman = cge.setVelocity(pacman, {0,1}, 1)
						cge.changeSprite(pacman, npacman)
				elseif key == 203 then --left arrow key
						local npacman = cge.setVelocity(pacman, {-1,0}, 1)
						cge.changeSprite(pacman, npacman)
				elseif key == 205 then --right arrow key
						local npacman = cge.setVelocity(pacman, {1,0}, 1)
						cge.changeSprite(pacman, npacman)
				end
		end
		pacman = cge.getSprite("pacman")
end

term.clear()
term.setCursorPos(1,1)

Thanks for following my tutorial and for using CGE!

Updates:
Spoilerv1.0
^initial release
v1.1
+setSpriteAnimationFrame()
+animateSprites()
+animateSprite()
+getCurAnimation()
+updateVelocity()
+getVelocity()
+setVelocity()
+addSprites()
+changeSprite()
*createSprite()
*constructSprite()
*moveSprite()
^added tutorial
^lots of bug fixes!
v1.2
+getSpriteCode()
+readSpriteCode()
+readSprite()
+readAnimatedSprite()
+readMap()
+addGravity()
+removeGravity()
+removeGravity()
+getGravityPoints()
+updateGravity()
+getSpriteBounds()
+flipSprite()
+colorDraw()
^A few small bug fixes
(+ = new ; - = removed ; * = changed ; ^ = other)

Please reply like I said earlier :D/>/>

Thanks!
wilcomega #2
Posted 09 October 2012 - 03:30 PM
no pics no clicks
billysback #3
Posted 09 October 2012 - 03:36 PM
pics of what? it's an API, the code is up there if you are worried about malicious code look at it…
wilcomega #4
Posted 09 October 2012 - 08:31 PM
i mean like an example of what you can do with it. and make pics of that or something
billysback #5
Posted 09 October 2012 - 08:44 PM
you mean like the example program paste?
I'm creating a tutorial right now for creating a pacman game, I can attach a picture of the working pacman game once that is complete at the end, would that be enough?
billysback #6
Posted 10 October 2012 - 10:26 PM
UPDATE:
added a (hopefully) very in-depth tutorial for the newest version

- fixed A LOT of bugs :P/>/>
- added ability to animate sprites
- added ability to set and use sprite velocity for easier use of movement.

(look at updates for full list of function additions/changes)
ChaddJackson12 #7
Posted 14 October 2012 - 04:07 AM
Seems interesting, I am not smart enough to make a game yet. But I think there could be quite a few cool games made with this.
SeniorFight #8
Posted 14 October 2012 - 03:37 PM
Good idea :3
There is something i recommend:

Add dispGrav(sprite) to make a gravity for the sprite.
Add setGravBase(posX, posY) to make a base for gravity.
Add getSpriteCode() to get a string code of the sprite to share it by RedNet.
Add reverseSprite(sprite, side) to make a reversement of the sprite (like mirror)
That's all i recommend :)/>/>

Epic idea.
Not easy use… But gooood work with the sprites =D
billysback #9
Posted 14 October 2012 - 05:44 PM
I'll add getSpriteCode(), though getSprite() is just a table containing the sprite's code, if that makes sense…
I'll also add recieveSpriteCode() which just reverses it…


reverseSprite would be easy, however the gravity idea would be a bit more complicated;
would it work better as it's own function or integrated as an optional feature in the updateVelocity()?

Note:
I'm going to add color support; it would work in literrally exactly the same way but where the type is you would put the color of the pixel;
I'm debating whether to make it support Minecraft Color Tags or to make it run on its own (which would make it a hell of a lot harder for me and would be cause for a delay in an update; what do others think?)

Edit:
Coming in next update:
–Ability to get sprites and maps from files!
(Including animates sprites using multiple files)
–Ability to use color tags to create colored games (this and reading sprites from files means you could use a program such as CTR to create
–Colored sprites and use them in your game!
–reverseSprite()
–gravity

Edit #2:
The only thing I am waiting for now is permission to use marumaru's code, then I can update CGE with color support, gravity support, file reading support, code formatting support!

Edit #3:
A little note on the gravity:
SpoilerI created my own formula for deciding whether or not the sprite should be affected be the gravitational pull in question;
how it works is:
Each gravitational center has three bits of data attached to it:
x, y, force.
The force is basically the gravity's are of effect;
To decide if the force affects a certain sprite the following formula is calculated:

(x + y)/2 = f
where x = distance between sprite x and gravitational center x
y = distance between sprite y and gravitational center y
f = required force

then it checks if the gravitational center's force if greater than or equal to f.
Can anyone else think of a better way that this could work?
Tiin57 #10
Posted 14 October 2012 - 07:59 PM
Great work on this.
tommyroyall #11
Posted 14 October 2012 - 08:15 PM
Btw, on the pac-man example, there's quite a few bugs. Copy the exact code from the end, then try to run it. I've found a couple already.
billysback #12
Posted 14 October 2012 - 08:30 PM
Updated the tutorial so it works, sorry :)/>/>
(the map and wall tables are messed up formatted wise whenever you copy them, don't really know why and it doesn't seem to be something I can fix)
billysback #13
Posted 15 October 2012 - 04:04 PM
Updated CGE:
look at "Updates" Spoiler!
(Main additions: Color support using MCT format and Gravity!)

NOTE:
I am currently creating a CGE script.
As CGE has a ridiculous amount of functions it won't call function and will instead run programs…
faubiguy #14
Posted 20 October 2012 - 05:40 PM
Great work. I'm using this for a Tetris game. I have two questions, is it possible to rotate sprites, or should I create a separate sprite for each frame of rotation? Also, does checkCollision return true if there is a collision between a space and a solid character or two spaces, or only between two characters? What about for colors?
billysback #15
Posted 21 October 2012 - 01:17 PM
checkCollision will return true if the sprite collides in any way with any of the sprites in the table.
Colors should work in the exact same way, except any color in your sprite will collide even if it is white (for example)

There isn't a rotate function, but if you look at this thread:
http://www.computerc...__fromsearch__1
(look at the last post)
You should be able to see how you could rotate it by using the flip function.
faubiguy #16
Posted 21 October 2012 - 02:29 PM
Thanks. One other thing, how can I make a sprite with color? Its probably pretty simple, but I can't find it in your list of functions or tutorial.
billysback #17
Posted 21 October 2012 - 04:48 PM
You use the normal functions in exactly the same way but just put MCT tags instead of characters.
faubiguy #18
Posted 22 October 2012 - 03:25 AM
constructSprite and createSprite apparently don't support color tags due to the way they work. How do I make colored sprites? (I'd prefer not to read from files as I'd like my game to be contained in one file. Hard-coding the sprites isn't an issue.)

EDIT: Also the getSpriteBounds function returns the lower-right bounds twice instead of top-left bounds and lower-right bounds
billysback #19
Posted 22 October 2012 - 04:14 PM
only constructSprite doesn't support colors because it gets each seperate character in each string in the table the sprite is created using, however because of how createSprite works (each character being in it's own string) it DOES support color support, so if you put color tags in the ttable and use colorDraw() then the game will detect that character as a color tag and draw it as a color.

I could add a constructColorSprite which would be the same as constructSprite but it gets each character by splitting the string at a space.
I will fix getSpriteBounds for the next update, if you want to fix it your self go to line 393 and copy in this code down to line 416
Spoiler

function getSpriteBounds(sprite)
        local upx = -1
        local upy = -1
        local downx = -1
        local downy = -1
        for i,v in ipairs(sprite) do
                local splt = split(v, ":")
                local x = splt[1]
                local y = splt[2]
                if upx == -1 then upx = x else
                        if x > upx then upx = x end
                end
                if upy == -1 then upy = y else
                        if y > upx then upy = y end
                end
                if downx == -1 then downx = x else
                        if x < downx then downx = x end
                end
                if downy == -1 then downy = y else
                        if y < downy then downy = y end
                end
        end
        return {upx, upy, downx, downy}
end
faubiguy #20
Posted 22 October 2012 - 04:51 PM
Ok, thanks. Sorry for assuming that createSprite wouldn't work.

Could you add a function for getting a list of all pixels in a sprite? Something like {{1, 1, "#"}, {2, 1, ">"}, {1, 2, "#"}, {2, 2, ">"}} for the sprite
#>
#>
I think that's similar to how sprite "objects" work, so it shouldn't be too hard to do.

Also is there any way to use magenta in sprites? MCT doesn't have a magenta tag.
billysback #21
Posted 22 October 2012 - 06:07 PM
For the getting the pixels do you mean return a table containing all of the pixels of the sprite in the correct set up, like in your code?

And for magenta, could you not use purple? (&amp;5)
If not I'll add a new tag for it :)/>/>
faubiguy #22
Posted 22 October 2012 - 06:10 PM
Yes, as in a table of tables, one for each pixel in the sprite, in the format {x, y, pixelChar}

Purple would probably work fine, but its still nice to have the full range of colors, including purple and brown.
billysback #23
Posted 22 October 2012 - 06:18 PM
So you just want the x,y,pixelChar data right?
If so then put this code at around 475 (anywhere in the middle will do)
Spoiler

function getSpritePixelData(sprite)
    local table = {}
    for i,v in ipairs(sprite) do
        local splt = split(v, ":")
        table[#table + 1] = {splt[0], splt[1], splt[2]}
    end
    return table
end

You might as well add this line as well, I added it in a dev build for AW.
Spoiler

function getSpriteLineData(line)
    local splt = split(line, ":")
    -- returns x, y, type, name, max-animation-frame, current-animation-frame, current-veloctiy
    return tonumber(splt[1]), tonumber(splt[2]), splt[3], splt[4], tonumber(splt[5]), tonumber(splt[6]), splt[7]
end  

usage would be:

local x, y, type, name, maxani, curani, curv = getSpriteLineData(sprite[n])
n is the index of the line you are reading.
faubiguy #24
Posted 22 October 2012 - 06:21 PM
Thanks, this will help with the piece stacking for my game.
billysback #25
Posted 22 October 2012 - 06:23 PM
also, if you want to add your own custom colors, you can do that easily by editing the getColor() function and adding:

	    elseif mctag == "tag" then
			    return colors.color
somewhere amongst the other lines like that, just so you know :)/>/>
(I will add support for other colors for an upcoming update, I just wanna do a bit more bug testing first :)/>/>
phyzix5761 #26
Posted 23 October 2012 - 06:47 PM
When I try to run the example (or any program with the CGE functions for that matter) it gives me an error when trying to call cge functions. "Attempt to index ? (a nil value)"

Any ideas why?
billysback #27
Posted 23 October 2012 - 07:30 PM
have you properly installed CGE? (into your lua/rom/apis)
ETHANATOR360 #28
Posted 11 November 2012 - 04:29 PM
cool +1 using this in my game
Mads #29
Posted 13 November 2012 - 06:02 AM
Why would you ever make a game engine using only one source file? It's generally a bad idea to have all of your classes(Not REALLY classes) in one single file, as it will easily get cluttered, and it is also confusing when looking at.

I would recommend writing a require() function, and using that.
billysback #30
Posted 13 November 2012 - 06:17 AM
I wanted to decrease complication of installation; basically I wanted to only have one source file.

Also, this was created a while a go and I am only going to be updating it if someone finds that there is something wrong with it; which brakes it.
The LAST thing I am going to do is rewrite it, if your looking for something a little bit similar to this but uses classes then go to my Art API…
SeniorFight #31
Posted 19 June 2013 - 03:37 AM
Now, as you added those things… What about adding a *collision* event ? :)/>

If two gaming sprites (Player1 and Pirates) are touching, then the os should get a new event called *collision*, returning the X and Y position WHERE it touched another picture. It's complicated, i know. But if you transform everything into a table, it will be hilariously easy!
RoD #32
Posted 30 March 2014 - 10:27 AM
Screenies are a great way of getting more downloads and feedback, you should post some. Any ways, i will see this because i am working on a game engine as well and i wanted to compare. :)/>
——————————————–
I have tested and there is and error line 21 attempt to index nil (in the cgexample program).
I think that its because you are using an api. If you want this game to work to other people i suggest you to do one of those:
  • Add the api to the installation;
  • Implement the api code in the final game code.
Hope you fix it, because the peaplo that didnt install the CGE can't play the game, wich means: only the game devs can play it. :P/>
Good job anyways.
sci4me #33
Posted 30 March 2014 - 04:53 PM
yeah, no pics no clicks. show some games made with it…
Engineer #34
Posted 30 March 2014 - 04:56 PM
yeah, no pics no clicks. show some games made with it…
Really, thats some useless advice. If people need pictures they dont belong here. The documentation should be enough,
RoD #35
Posted 30 March 2014 - 05:18 PM
yeah, no pics no clicks. show some games made with it…
Really, thats some useless advice. If people need pictures they dont belong here. The documentation should be enough,
And it is enough, but images are more atractive and people stay longer and get more interesed in the porgram. :)/>
sci4me #36
Posted 30 March 2014 - 05:40 PM
yeah, no pics no clicks. show some games made with it…
Really, thats some useless advice. If people need pictures they dont belong here. The documentation should be enough,
And it is enough, but images are more atractive and people stay longer and get more interesed in the porgram. :)/>

Well, API or no API, no pics no clicks applies. It doesnt interest me until I see a pic that changes my mind.. not just this though. That applies to ALL things. (nearly all..)
CometWolf #37
Posted 30 March 2014 - 06:14 PM
So what you're saying is, you've basically got ADD, good to know…
The point of this API isn't to be a visual aid. It's to make functional game mechanics, as such the functions it offers are far more important to anyone interested in using it.
RoD #38
Posted 30 March 2014 - 06:31 PM
So what you're saying is, you've basically got ADD, good to know…
The point of this API isn't to be a visual aid. It's to make functional game mechanics, as such the functions it offers are far more important to anyone interested in using it.
Agree.
pfgcomputercraft #39
Posted 24 April 2014 - 02:06 AM
have you properly installed CGE? (into your lua/rom/apis)
… that's installing it correctly? shouldn't you just use the os.loadAPI function