質問

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?

役に立ちましたか?

解決

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

他のヒント

You're on the right idea, except that to be REALLY artist driven, you should use a consistent set of layers. Generate multiple images for each layer class.

  1. Fuselage
  2. Cockpit
  3. Wings
  4. Wing-adornments
  5. Rear engines

and so on.

Each of these layers are the SAME size and designed by the artist to be correctly centered. :) Also note that any of these layers can contain anything, even be empty. Now simple randomization should give you a nice, believable and unique ship. :)

It is also entirely possible for you to add pixel coordinates alongside each set of "engine" class layer image which you can use as the "center" of differently positioned jet engine flames.

I actually did this a long time ago! I went into way more details then you will. I will try to find a picture, if I still have one lying around, hold on. I might even have the old code. I would gladly give it to you. LMAO, what an archive of old projects, can't believe I made all this stuff before ever working in the field... Doesn't seem like I have it, but I do have something of a similar nature, and it might even be inside that project, let me put it in Eclipse and check it out. Nope, wasn't the project I was looking for, nor does it build, the bugger has 33 errors. I also lost my randomized planet generation code, and probably a whole ton of other projects.

Advice:

I tried generating an entire ship from scratch, meaning almost no constraints. It worked by sort of randomizing points, and then I would mirror image it. I would get results such as this: (well it won't let me post images, sorry).

What I would suggest, is limiting the possibilities, and using various parts each with their own type, with the ability to connect to other parts of a specific type. Like for a house, you would do the following. Walls, connect to other walls, some walls have window slot. Some walls have door slot, etc. A wall might have a window slot and a waterline slot.

In this case of spaceships the above would make a lot more sense. Make sure that each type of piece follows a downward trend, so the base of the ship would be a 4, which would connect to one or more 3's, which would each connect to one or more 2's, which would each connect to one or more 1's. When randomly selecting an item, I would suggest that item be used throughout, like a single type of laser weapon. Also, be sure to consider allowing items to scale in size, so that you can better reuse parts.

I think it is an amazing project, but also a very time consuming one to do right. I hope you have fun, and let me know how it goes!

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top