Sprites

Hi,

I’m looking for a script or whatever to quickly make a sprite sheet. Basically, ypu place the camera at the angle you want, the python script will render a small img (typically 32*32) then, move the keyframe up one, render another img, until all the frames are rendered. Then it will mosh all the renders of the frame together and poop out a sprite sheet. Anyone know of a script that would be capable, or know how to do this?

example of a sprite sheet can be found here if you don’t know what I’m talking about.

Thanks,
Rozzy

I wrote a short script (at the end of this thread) that has about half (maybe 1/3 is a better estimate) the functionality of what you’re asking for. I could fix it up some more so that it renders you’re key frames like you ask (I got busy with all sorts of projects, and kind of lost track of that script).

The moshing together might be better done by an external script, but since its from Blender, might as well do it there I suppose.

Edit:


import Blender
from Blender import BGL, Camera, Constraint, Image, Mathutils, Object
import bpy

try:
    import math
    cos = math.cos
    sin = math.sin
    PI = math.pi
except:
    print 'A full python install is required to run this script'

####################################
#
#    User Params
#
####################################

# Object to Track To (for camera to follow)
trackOb = 'Suzanne'

# Path to render file, excluding filename
renderPath = '/users/yourplace/rendersomething/'  # Must have this end slash!

# Filename to render to
filename = 'temp.png'

XYSteps = 4 #Number of steps in the x-y plane (circular steps)
YZSteps = 1 #Number of steps in the y-z plane, not really currently used, just leave at 1 for now...

startLoc = Mathutils.Vector([4, 0, 0])

# Key Framing
startFrame = 1
endFrame = 11
frameStep = 5

#####################################
def blitImage(dest, source, start):
    sourceSize = source.getSize()
    for i in xrange(sourceSize[0]):
        for j in xrange(sourceSize[1]):
            dest.setPixelF(start[0]+i, start[1]+j, source.getPixelF(i, j))

class SceneObject(object):
    def __init__(self, scene):
        self.scene = scene
        
    def addToScene(self, data, name):
        self.ob = self.scene.objects.new(data, name)
        return self.ob
    
    def removeFromScene(self):
        self.scene.objects.unlink(self.ob)
        
    def setLocation(self, loc):
        self.ob.setLocation(*list(loc))
    
class TrackedCamera(SceneObject):
    def __init__(self, scn, type):
        SceneObject.__init__(self, scn)
        
        self.__cam = Camera.New(type, 'TrackedCam')
        self.__camOb = self.addToScene(self.__cam, 'TrackedCam')
        
    def __del__(self):
        self.removeFromScene()

    def trackToObject(self, object, track = Constraint.Settings.TRACKNEGZ, up = Constraint.Settings.UPY):
        con = self.__camOb.constraints.append(Constraint.Type.TRACKTO)
        con[Constraint.Settings.TARGET] = object
        con[Constraint.Settings.TRACK] = track
        con[Constraint.Settings.UP] = up
        
    def makeActive(self):
        self.scene.objects.camera = self.__camOb
        
########################################
scn = bpy.data.scenes.active

TWOPI = 2*PI

xyStepSize = TWOPI / XYSteps
radius = (startLoc[0]*startLoc[0] + startLoc[1]*startLoc[1])**0.5
        
tc = TrackedCamera(scn, 'persp')
ob = Object.Get(trackOb)
tc.trackToObject(ob)
tc.setLocation(startLoc)
tc.makeActive()

curXYTheta = Mathutils.AngleBetweenVecs(Mathutils.Vector(radius, 0), Mathutils.Vector(startLoc[0], startLoc[1]))
curXYTheta *= PI/180

rc = tc.scene.getRenderingContext()
xR = rc.imageSizeX()
yR = rc.imageSizeY()
rc.setRenderPath(renderPath)

imageSave = Image.New('Output', xR * (int(((endFrame-startFrame) / frameStep)) + 1), yR * XYSteps, 32)

curXPix = 0
curYPix = 0

curFrame = startFrame
while curFrame <= endFrame:
    Blender.Set('curframe', curFrame)
    
    for i in xrange(YZSteps):
        zLoc = startLoc[2]
        for j in xrange(XYSteps):
            xLoc = radius * cos(curXYTheta)
            yLoc = radius * sin(curXYTheta)
    
            tc.setLocation([xLoc, yLoc, zLoc])
            rc.render()
        
            rc.saveRenderedImage(filename)
        
            rend = Image.Load(renderPath+filename)
            rend.reload()
        
            blitImage(imageSave, rend, [curXPix, curYPix])
            
            curXYTheta += xyStepSize
            curYPix += yR
        
    curYPix = 0
    curXPix += xR
    curFrame += frameStep
    
del tc
imageSave.makeCurrent()
Blender.Redraw(-1)

Should do about what you want. The sprites are stored across for each frame instead of down. It would be possible to change it, though.

Hopefully the parameters are well self-explanatory enough, if not let me know and I’ll be glad to elaborate. Note that it uses the current render size and calculates everything from there. So if you want it 32x32, just set that the normal way. And one more note, you’ll have to save out the image it generates on your own…

Perhaps one day I’ll make GUI and make a proper script of this…

Tyvm forTe!

How did I miss the original thread in first place? This script will come in handy, thank you forTe! …and Rozzy for asking this. :slight_smile: