AylinCE Grandmaster Cheater Supreme
  Reputation: 37
  Joined: 16 Feb 2017 Posts: 1530
 
  | 
		
			
				 Posted: Sun Jul 13, 2025 5:58 pm    Post subject: Create Games with CE (Holiday Fun) | 
				       | 
			 
			
				
  | 
			 
			
				Create Games with CE (Holiday Fun)
 
 
I'm offering a coding primer that's just for fun and can be further shaped by your imagination.
 
 
What will we do?
 
 
1) We'll structure our images and GIFs as "Sprite Sheets" to take up less space.
 
2) Using the main code snippet and accurate calculations,
 
we'll divide our Sprite Sheet image into pieces and transfer them to the spreadsheets.
 
3) We'll complete and test our first movements with a timer, a form, and a few buttons.
 
 
So, let's get started.
 
 
1) Creating Sprite Sheet Characters:
 
Create this completely free and easy-to-create, download, and use template,
 
which includes a wide variety of character, costume, skin, armor, and weapon options.
 
 
https://liberatedpixelcup.github.io/Universal-LPC-Spritesheet-Character-Generator
 
 
2) Crop the character image you created, which includes many movement variations, and where each line adds up to a GIF, and arrange it in squares on a table.
 
 
 	  | Code: | 	 		  -- Direction-row mapping for each sprite (customizable by user)
 
local allDirections = { }
 
 
-- Extract individual frames from a sprite sheet
 
-- Organizes as: [spriteIndex][directionName][frameIndex] = picture
 
function extractFrames(spriteFile, frameCounts, frameWidth, frameHeight)
 
  local sprite = createPicture()
 
  sprite.loadFromStream(findTableFile(spriteFile).stream)
 
 
  local allFrames = {}
 
  local currentRow = 0
 
 
  for spriteIndex = 1, 2 do
 
    allFrames[spriteIndex] = {}
 
    for dirName, rowIndex in pairs(allDirections[spriteIndex]) do
 
      local frameCount = frameCounts[rowIndex]
 
      local y = (rowIndex - 1) * frameHeight
 
      local rowFrames = {}
 
 
      for frameIndex = 1, frameCount do
 
        local framePic = createPicture()
 
        framePic.Bitmap.Width = frameWidth
 
        framePic.Bitmap.Height = frameHeight
 
        framePic.Bitmap.Canvas.copyRect(
 
          0, 0, frameWidth, frameHeight,
 
          sprite.Bitmap.Canvas,
 
          (frameIndex - 1) * frameWidth, y,
 
          frameIndex * frameWidth, y + frameHeight
 
        )
 
        framePic.Transparent = true
 
        framePic.Bitmap.Transparent = true
 
        framePic.Bitmap.TransparentColor = framePic.Bitmap.Canvas.getPixel(0, 0)
 
        table.insert(rowFrames, framePic)
 
      end
 
 
      allFrames[spriteIndex][dirName] = rowFrames
 
    end
 
  end
 
 
  return allFrames
 
end | 	  
 
 
Note:
 
Don't use the entire image.
 
Crop only the keyframes in a photo editor.
 
Make sure to center and crop between the lines correctly.
 
Then, count the total number of frames in the image from left to right (the example image has a maximum of 9 frames).
 
Divide this by the width to calculate the width of each frame:
 
(In the example image, the width is 1.152, the maximum number of frames is 9. 1152/9 = 128
 
frameWidth = 128)
 
Similarly, calculate the frame height:
 
(In the example image, the height is 1014, the number of frames is 8. 1014/8 = 126.75,
 
frameHeight = 126.75)
 
Now create a table: How many frames are in each row?
 
(The example image has 4x9 and 4x6. So, the table is:
 
frameCounts = {9,9,9,9,6,6,6,6}
 
Finally, add the image to the CE (Table>>add file) and simply name the image in the script: spriteFile = "female3.png"
 
 
If everything went well, your character table is ready.
 
 
The rest is up to your imagination:
 
 
Here's a ready-made script using the example image:
 
 
Note: To move the images, enter the number 1 or 2 in the edit box.
 
 
 	  | Code: | 	 		  -- Direction-row mapping for each sprite (customizable by user)
 
local allDirections = { }
 
 
-- Extract individual frames from a sprite sheet
 
-- Organizes as: [spriteIndex][directionName][frameIndex] = picture
 
function extractFrames(spriteFile, frameCounts, frameWidth, frameHeight)
 
  local sprite = createPicture()
 
  sprite.loadFromStream(findTableFile(spriteFile).stream)
 
 
  local allFrames = {}
 
  local currentRow = 0
 
 
  for spriteIndex = 1, 2 do
 
    allFrames[spriteIndex] = {}
 
    for dirName, rowIndex in pairs(allDirections[spriteIndex]) do
 
      local frameCount = frameCounts[rowIndex]
 
      local y = (rowIndex - 1) * frameHeight
 
      local rowFrames = {}
 
 
      for frameIndex = 1, frameCount do
 
        local framePic = createPicture()
 
        framePic.Bitmap.Width = frameWidth
 
        framePic.Bitmap.Height = frameHeight
 
        framePic.Bitmap.Canvas.copyRect(
 
          0, 0, frameWidth, frameHeight,
 
          sprite.Bitmap.Canvas,
 
          (frameIndex - 1) * frameWidth, y,
 
          frameIndex * frameWidth, y + frameHeight
 
        )
 
        framePic.Transparent = true
 
        framePic.Bitmap.Transparent = true
 
        framePic.Bitmap.TransparentColor = framePic.Bitmap.Canvas.getPixel(0, 0)
 
        table.insert(rowFrames, framePic)
 
      end
 
 
      allFrames[spriteIndex][dirName] = rowFrames
 
    end
 
  end
 
 
  return allFrames
 
end
 
 
--============================================================--
 
-- Direction-to-row mapping for each sprite
 
-- Example: sprite 1 uses rows 1–4, sprite 2 uses rows 5–8
 
allDirections = {
 
  [1] = { ["↑"]=1, ["←"]=2, ["↓"]=3, ["→"]=4 },
 
  [2] = { ["↑"]=5, ["←"]=6, ["↓"]=7, ["→"]=8 }
 
}
 
 
-- Frame setup
 
local frameCounts = {9,9,9,9,6,6,6,6}
 
local spriteFile = "female3.png"
 
local frameWidth, frameHeight = 128, 126.75
 
 
-- Extract and store all sprite frames
 
local allFrames = extractFrames(spriteFile, frameCounts, frameWidth, frameHeight)
 
 
--=============================================================--
 
-- Runtime state: sprite control and animation trackers
 
local imgArray = {}
 
local currentFrameIndex = { [1]=1, [2]=1 }
 
local spriteDirection = { [1]="↑", [2]="↑" }
 
local activeSprite = 1
 
 
-- Main UI form
 
if f2 then f2.Destroy() end
 
f2 = createForm()
 
f2.Width = 660
 
f2.Height = 450
 
 
f2.OnClose=function()
 
if frameTmr1 then frameTmr1.Destroy() frameTmr1 = nil end
 
f2.Destroy()
 
end
 
 
-- Image containers for sprites
 
for i=1, 2 do
 
  imgArray[i] = createImage(f2)
 
  imgArray[i].Left = (i == 1) and 40 or 500
 
  imgArray[i].Top = 350
 
  imgArray[i].Width = frameWidth
 
  imgArray[i].Height = frameHeight
 
  imgArray[i].Stretch = true
 
  imgArray[i].Transparent = true
 
end
 
 
-- Animation timer
 
if frameTmr1 then frameTmr1.Destroy() frameTmr1 = nil end
 
frameTmr1 = createTimer(f2)
 
frameTmr1.Interval = 125
 
frameTmr1.OnTimer = function()
 
  for i=1, 2 do
 
    local dir = spriteDirection[i]
 
    local frames = allFrames[i][dir]
 
    if frames and #frames > 0 then
 
      imgArray[i].Picture = frames[currentFrameIndex[i]]
 
      currentFrameIndex[i] = currentFrameIndex[i] % #frames + 1
 
    end
 
  end
 
end
 
 
-- Sprite selector (editbox)
 
local indexEdit = createEdit(f2)
 
indexEdit.Left = 430
 
indexEdit.Top = 390
 
indexEdit.Width = 40
 
indexEdit.Text = tostring(activeSprite)
 
 
indexEdit.OnChange = function(sender)
 
  local val = tonumber(sender.Text)
 
  if val == 1 or val == 2 then activeSprite = val end
 
end
 
 
-- Movement function updates position and direction
 
local function moveSprite(dx, dy, direction)
 
  spriteDirection[activeSprite] = direction
 
  imgArray[activeSprite].Left = imgArray[activeSprite].Left + dx
 
  imgArray[activeSprite].Top = imgArray[activeSprite].Top + dy
 
end
 
 
-- Directional movement buttons
 
local function createDirButton(caption, x, y, dx, dy)
 
  local btn = createButton(f2)
 
  btn.Left = x
 
  btn.Top = y
 
  btn.Caption = caption
 
  btn.OnClick = function() moveSprite(dx, dy, caption) end
 
end
 
 
createDirButton("←", 210, 390, -15, 0)
 
createDirButton("→", 335, 390, 15, 0)
 
createDirButton("↑", 275, 360, 0, -15)
 
createDirButton("↓", 275, 420, 0, 15)
 
 | 	  
 
 
(If you can't see the image, try refreshing the page.)
 
 
If you write a good game, the next step should be saving the data to a global server.
 
 
User registration...
 
User login system...
 
User data...
 
Online chat window...
 
And loading the main form with a secure login.
 
 
I've compiled all of this into a single program and integrated it into CE with "aceserver.exe."
 
 
But that's a topic for another article; it's still being developed.    
 
 
Until we meet again on another fun and exciting topic, enjoy it!  
 _________________
  | 
			 
		  |