Skip to content

Latest commit

 

History

History
336 lines (279 loc) · 9.49 KB

File metadata and controls

336 lines (279 loc) · 9.49 KB

Adding Graphical Images to the Game

This guide shows you how to replace the procedural graphics with image sprites for the spaceship, bullets, and other game objects.

Step 1: Prepare Your Images

Recommended Image Formats

  • PNG (with transparency support)
  • JPG (for backgrounds without transparency)

Recommended Sizes

  • Spaceship: 50x50 pixels to 100x100 pixels
  • Bullets: 8x16 pixels to 16x32 pixels
  • Enemies: 40x40 pixels to 80x80 pixels
  • Background: 800x600 pixels (or larger for tiling)

Where to Place Images

Put all image files in the assets/ directory:

assets/
├── spaceship.png
├── bullet.png
├── enemy1.png
├── enemy2.png
├── background.png
└── explosion.png

Step 2: Load Images in main.lua

Add this section near the top of main.lua, after the initial variables:

-- Images
local images = {
    player = nil,
    bullet = nil,
    enemy = nil,
    background = nil
}

-- Load images in love.load()
function love.load()
    love.window.setTitle("Space Shooter - Lua/LOVE2D Example")
    love.graphics.setBackgroundColor(0.02, 0.02, 0.08)
    math.randomseed(os.time())
    initStars()
    
    -- Load image files (will fallback to procedural if not found)
    loadImages()
end

function loadImages()
    -- Try to load images, use pcall to handle missing files gracefully
    local success, img
    
    success, img = pcall(love.graphics.newImage, "assets/spaceship.png")
    if success then
        images.player = img
        print("Loaded: spaceship.png")
    end
    
    success, img = pcall(love.graphics.newImage, "assets/bullet.png")
    if success then
        images.bullet = img
        print("Loaded: bullet.png")
    end
    
    success, img = pcall(love.graphics.newImage, "assets/enemy.png")
    if success then
        images.enemy = img
        print("Loaded: enemy.png")
    end
    
    success, img = pcall(love.graphics.newImage, "assets/background.png")
    if success then
        images.background = img
        print("Loaded: background.png")
    end
end

Step 3: Modify Drawing Functions

Replace drawPlayer() Function

-- Draw player ship (with image or procedural fallback)
local function drawPlayer()
    local x, y = player.x, player.y
    local w, h = player.width, player.height

    if images.player then
        -- Draw the spaceship image
        love.graphics.setColor(1, 1, 1, 1)
        local img_w = images.player:getWidth()
        local img_h = images.player:getHeight()
        local scale_x = w / img_w
        local scale_y = h / img_h
        
        love.graphics.draw(
            images.player,
            x, y,
            0,              -- rotation
            scale_x, scale_y,
            img_w/2, img_h/2  -- origin (center)
        )
    else
        -- Fallback to procedural graphics (existing code)
        -- Glow effect
        for i = 15, 1, -3 do
            local alpha = 0.1 * (1 - i / 15)
            love.graphics.setColor(player.color[1], player.color[2], player.color[3], alpha)
            love.graphics.polygon("fill",
                x, y - h/2 - i,
                x - w/2 - i, y + h/2 + i,
                x + w/2 + i, y + h/2 + i)
        end

        -- Main ship body
        love.graphics.setColor(player.color[1], player.color[2], player.color[3], 1)
        love.graphics.polygon("fill",
            x, y - h/2,
            x - w/2, y + h/2,
            x + w/2, y + h/2)

        -- Cockpit
        love.graphics.setColor(0.1, 0.2, 0.3, 1)
        love.graphics.polygon("fill",
            x, y - h/4,
            x - w/4, y + h/4,
            x + w/4, y + h/4)

        -- Engine glow
        love.graphics.setColor(1, 0.5, 0.2, 0.8)
        love.graphics.polygon("fill",
            x - w/4, y + h/2,
            x, y + h/2 + 15 + math.random(0, 5),
            x + w/4, y + h/2)
    end
end

Modify Bullet Drawing in love.draw()

Find the bullet drawing section and replace it:

-- Draw bullets
for _, bullet in ipairs(bullets) do
    if images.bullet then
        -- Draw bullet image
        love.graphics.setColor(1, 1, 1, 1)
        local img_w = images.bullet:getWidth()
        local img_h = images.bullet:getHeight()
        local scale_x = bullet.width / img_w
        local scale_y = bullet.height / img_h
        
        love.graphics.draw(
            images.bullet,
            bullet.x, bullet.y,
            0,
            scale_x, scale_y,
            img_w/2, img_h/2
        )
    else
        -- Fallback to procedural bullet (existing code)
        for i = 8, 1, -2 do
            local alpha = 0.2 * (1 - i / 8)
            love.graphics.setColor(bullet.color[1], bullet.color[2], bullet.color[3], alpha)
            love.graphics.rectangle("fill",
                bullet.x - bullet.width/2 - i,
                bullet.y - bullet.height/2 - i,
                bullet.width + i*2,
                bullet.height + i*2)
        end
        love.graphics.setColor(bullet.color[1], bullet.color[2], bullet.color[3], 1)
        love.graphics.rectangle("fill", bullet.x - bullet.width/2, bullet.y - bullet.height/2, bullet.width, bullet.height)
    end
end

Modify Enemy Drawing

Find the enemy drawing section and replace it:

-- Draw enemies
for _, enemy in ipairs(enemies) do
    if images.enemy then
        -- Draw enemy image
        love.graphics.setColor(1, 1, 1, 1)
        local img_w = images.enemy:getWidth()
        local img_h = images.enemy:getHeight()
        local scale_x = enemy.width / img_w
        local scale_y = enemy.height / img_h
        
        love.graphics.draw(
            images.enemy,
            enemy.x, enemy.y,
            0,
            scale_x, scale_y,
            img_w/2, img_h/2
        )
    else
        -- Fallback to procedural (existing code)
        drawGlowingRect(enemy.x, enemy.y, enemy.width, enemy.height, enemy.color)
    end
end

Step 4: Add Background Image (Optional)

In love.draw(), add at the very beginning:

function love.draw()
    -- Draw background image if available
    if images.background then
        love.graphics.setColor(1, 1, 1, 0.5)  -- Semi-transparent
        love.graphics.draw(images.background, 0, 0)
    end
    
    -- Draw stars (existing code)
    for _, star in ipairs(stars) do
        love.graphics.setColor(1, 1, 1, star.brightness)
        love.graphics.circle("fill", star.x, star.y, star.size)
    end
    
    -- ... rest of the draw code
end

Step 5: Creating or Finding Images

Option 1: Create Your Own

Online Sprite Editor (No Installation Required):

  • XcaliburMoon Sprite Paint Tool: https://xcm-sandbox.tech/sprite-paint-tool/
    • Free browser-based sprite editor developed by XcaliburMoon
    • Perfect for creating game sprites
    • No software installation needed
    • Export as PNG

Desktop Image Editors:

  • GIMP (free, cross-platform)
  • Photoshop
  • Aseprite (pixel art)
  • Krita (free)
  • Paint.NET (Windows)

Option 2: Free Resources

Download free game sprites from:

  • OpenGameArt.org
  • itch.io (free assets section)
  • Kenney.nl (free game assets)
  • Craftpix.net (some free assets)

Option 3: Generate with AI

Use AI tools to generate sprites:

  • DALL-E
  • Midjourney
  • Stable Diffusion

Complete Example Code Snippet

Here's a complete modification you can add to main.lua:

-- Add after the initial variables section
local images = {}

-- Modify love.load()
function love.load()
    love.window.setTitle("Space Shooter - Lua/LOVE2D Example")
    love.graphics.setBackgroundColor(0.02, 0.02, 0.08)
    math.randomseed(os.time())
    initStars()
    
    -- Load images
    images.player = loadImage("assets/spaceship.png")
    images.bullet = loadImage("assets/bullet.png")
    images.enemy = loadImage("assets/enemy.png")
    images.background = loadImage("assets/background.png")
end

-- Helper function to safely load images
function loadImage(path)
    local success, img = pcall(love.graphics.newImage, path)
    if success then
        print("Loaded: " .. path)
        return img
    else
        print("Could not load: " .. path .. " (using procedural graphics)")
        return nil
    end
end

Image Drawing Parameters Explained

The love.graphics.draw() function parameters:

love.graphics.draw(
    image,      -- The image object
    x, y,       -- Position (center if origin is set)
    rotation,   -- Rotation in radians (0 = no rotation)
    scale_x,    -- Horizontal scale (1 = original size)
    scale_y,    -- Vertical scale (1 = original size)
    origin_x,   -- X offset for rotation/scaling center
    origin_y    -- Y offset for rotation/scaling center
)

Tips

  1. Use Transparent PNGs: Save images with transparent backgrounds for best results
  2. Consistent Art Style: Keep all sprites in the same art style (pixel art, vector, realistic, etc.)
  3. Power of 2 Sizes: Use image dimensions that are powers of 2 (32, 64, 128, 256) for better performance
  4. Sprite Sheets: For animations, use sprite sheets and extract frames
  5. Test Without Images: The code includes fallbacks so the game works with or without images

Testing

  1. Place an image in the assets/ folder
  2. Run the game with love . or ./start.sh
  3. Check console output to see which images loaded successfully
  4. If an image doesn't load, the game will use procedural graphics as fallback

Next Steps

  • Add rotation to bullets: Change rotation parameter from 0 to math.pi/2 for vertical bullets
  • Add engine fire animation behind the spaceship
  • Create explosion sprite sheets for better explosion effects
  • Add parallax background layers with multiple images