Search code examples
c#graphicsprocedural-programming

procedural generation of spaceship sprites


I've been researching this topic for a couple of days and have an idea how how it might work, but I thought I'd post here for some other ideas.

What I'd like to do is generate spaceship sprites/images to be used in a game. The look and feel should be similar to these: spaceship sprites

Basically, my idea boils down to something like this:

  1. Generate a base shape that forms the "core" of the ship. Shapes could include circles, ovals, diamonds, rounded-corner rectangles, etc.

  2. Generate smaller sub-shapes that are either overlayed on the core shape, or connected via a simple pipe. (All sub-shapes are mirrored to create a symmetrical ship.)

  3. Generate even smaller sub-shapes (detail shapes), overlay them on any existing shape. (These form the "details" of the ship.)

  4. Choose 3-5 colors, randomly shade each shape so overlayed shapes are not the same color.

  5. Apply texturing or gradients to the core and sub-shapes (not detail shapes) to give the ship a 3-d look.

Does anyone out there know of a way to implement an algorithm such as this to achieve the desired look of the spaceships?


Solution

  • System.Drawing.Drawing2D.GraphicsPath might be helpful here for building up vector paths. You can then fill and add a stroke to these paths to create the different shapes.

    You can use System.Drawing.Drawing2D.LinearGradientBrush for your gradients.

    Would love to see your code if you get something going. This seems like a cool idea.

    Just for fun I knocked this together in VB.NET:

    Imports System.Drawing.Drawing2D
    
    Public MustInherit Class ShipShape
        Public Layout As New Rectangle(0, 0, 128, 128)
        Public MustOverride Sub Draw(ByVal g As Graphics)
    
        Public Shared Sub DrawRoundedRectangle(ByVal gp As GraphicsPath, ByVal r As Rectangle, ByVal d As Integer)
            gp.AddArc(r.X, r.Y, d, d, 180, 90)
            gp.AddLine(CInt(r.X + d / 2), r.Y, CInt(r.X + r.Width - d / 2), r.Y)
            gp.AddArc(r.X + r.Width - d, r.Y, d, d, 270, 90)
            gp.AddLine(CInt(r.X + r.Width), CInt(r.Y + d / 2), CInt(r.X + r.Width), CInt(r.Y + r.Height - d / 2))
            gp.AddArc(r.X + r.Width - d, r.Y + r.Height - d, d, d, 0, 90)
            gp.AddLine(CInt(r.X + d / 2), CInt(r.Y + r.Height), CInt(r.X + r.Width - d / 2), CInt(r.Y + r.Height))
            gp.AddArc(r.X, r.Y + r.Height - d, d, d, 90, 90)
            gp.AddLine(r.X, CInt(r.Y + d / 2), r.X, CInt(r.Y + r.Height - d / 2))
        End Sub
    
        Public Shared Sub main()
            Dim b As New Bitmap(640, 480)
            Dim g As Graphics = Graphics.FromImage(b)
            g.Clear(Color.Magenta)
            Dim Hull As New HullShape
            Hull.Layout = New Rectangle(640 * 0.5 - 128 * 0.5, 480 * 0.5 - 128 * 0.5, 128, 128)
            Hull.Draw(g)
            Dim Wing1 As New HullShape
            Wing1.Layout = New Rectangle(Hull.Layout.X - 32, Hull.Layout.Y - 32, 32, Hull.Layout.Height + 64)
            Wing1.Draw(g)
            Dim Wing2 As New HullShape
            Wing2.Layout = New Rectangle(Hull.Layout.X + Hull.Layout.Width, Hull.Layout.Y - 32, 32, Hull.Layout.Height + 64)
            Wing2.Draw(g)
            b.Save("test.png")
        End Sub
    
    End Class
    
    Public Class HullShape
        Inherits ShipShape
        Public Overrides Sub Draw(ByVal g As System.Drawing.Graphics)
            Dim gp As New GraphicsPath
            ShipShape.DrawRoundedRectangle(gp, Layout, 30)
            Dim MetalBrush As New LinearGradientBrush(Layout, Color.Gainsboro, Color.Gray, 0)
            g.FillPath(MetalBrush, gp)
            g.DrawPath(Pens.Black, gp)
        End Sub
    End Class
    

    Output image