Author Topic: Blobmonster  (Read 8120 times)

Offline Albert

  • Dr. Type
  • ****
  • Posts: 257
    • View Profile
    • Blog
Blobmonster
« on: 2011-Feb-10 »
So Charlie has this tutorial and source code in BlitzMax: http://www.charliesgames.com/wordpress/?p=441
I ported it to glBasic, have fun!



Code: GLBasic [Select]
// --------------------------------- //
// Project: blobmonster
// Start: Friday, February 04, 2011
// IDE Version: 8.200

SETCURRENTDIR("Media") // seperate media and binaries?

//ported to glBasic by Bence Dobos, 2011

//How to make an Irukandji style blob monster.
//By Charlie Knight, 2009/2010
//http://www.charliesgames.com
//
//This code is public domain. Feel free to use as you please.
//If you use the code as a basis for your own blob monsters, let me know! I'd love to
//see what you came up with!
//
//The code is written using the Blitzmax language, but it should be fairly easy to port
//to C++/Java/Whatever with a suitable graphics library.
//
//the image blob.png can be found at http://www.charliesgames.com/wpimages/blob.png
//
//Cheers
//Charlie

GLOBAL KEY_ESCAPE=1
GLOBAL blob=0
GLOBAL w, h

//load the image
LOADSPRITE "blob.png", blob
GETSPRITESIZE blob, w, h

//create a blobMonster object
LOCAL test AS blobMonster

test.Create(10, 10)
//main loop
WHILE KEY(KEY_ESCAPE)=0
        //update and draw the blobmonster
        CLEARSCREEN
        test.Update()
        test.Draw()

        SHOWSCREEN
WEND
END
//Finished!

//simple class (type in glBasic) to hold a 2d coordinate
TYPE point
        x#
        y#
ENDTYPE

//here's the blob monster type
TYPE blobMonster

        //x and y coords
        x#
        y#

        //speed, try changing it
        speed# = 1

        //number of nodes along the body, try changing it to 100
        segments# = 10

        //array to hold the points along the body
        tail[] AS point

        time# = 0

        //function that returns a new blob monster object. Blitzmax equivalent (kind of)
        //of a constructor in C++/Java
        FUNCTION Create AS blobMonster:inX#, inY#
                DIM self.tail[self.segments]
                //starting point of the blob monster
                self.x = inX
                self.y = inY
                //give the tail some coordinates, just make them the same as the main x and y for now
                FOR i = 0 TO self.segments - 1
                        self.tail[i].x# = inX
                        self.tail[i].y# = inY
                NEXT

                RETURN self
        ENDFUNCTION

        FUNCTION Update%:
                //time is a bit misleading, it's used for all sorts of things
                INC self.time#, self.speed#

                //here the x and y coordinates are updated.
                //this uses the following as a basic rule for moving things
                //around a point in 2d space:
                //x=radius*cos(angle)+xOrigin
                //y=raduis*sin(angle)+yOrigin
                //this basically is the basis for anything that moves in this example
                //
                //the 2 lines of code below make the monster move around, but
                //you can change this to anything you like, try setting x and y to the mouse
                //coordinates for example
                self.y = (15 * COS(self.time * -6)) + (240 + (180 * SIN(self.time * 1.3)))
                self.x = (15 * SIN(self.time * -6)) + (320 + (200 * COS(self.time / 1.5)))

                //put the head of the tail at x,y coords
                self.tail[0].x = self.x
                self.tail[0].y = self.y

                //update the tail
                //basically, the points don//t move unless they//re further that 7 pixels
                //from the previous point. this gives the kind of springy effect as the
                //body stretches
                FOR i = 1 TO self.segments - 1
                                //calculate distance between the current point and the previous
                        LOCAL distX# = (self.tail[i - 1].x - tail[i].x)
                        LOCAL distY# = (self.tail[i - 1].y - tail[i].y)
                                LOCAL dist# = SQR(distX * distX + distY * distY)
                        //move if too far away
                        IF dist > 7
                                        //the (distX*0.2) bit makes the point move
                                        //just 20% of the distance. this makes the
                                        //movement smoother, and the point decelerate
                                        //as it gets closer to the target point.
                                        //try changing it to 1 (i.e 100%) to see what happens
                                        self.tail[i].x = self.tail[i].x + (distX * (0.3))
                        self.tail[i].y = self.tail[i].y + (distY * (0.3))
                        ENDIF

                NEXT

                RETURN FALSE
        ENDFUNCTION

        FUNCTION Draw:
                //time to draw stuff!

                //this sets the blend mode to LIGHTBLEND, or additive blending, which makes
                //the images progressively more bright as they overlap
                //ALPHAMODE LIGHTBLEND
                LOCAL color=RGB( 0, 200, 150 )
                LOCAL scale=1
                //###########
                //draw the main bit of the body
                //begin looping through the segments of the body
                FOR i = 0 TO self.segments - 1
                        //set the alpha transparency vaue to 0.15, pretty transparent
                        ALPHAMODE 0.15
                        //the  (0.5*sin(i*35)) bit basically bulges the size of the images being
                        //drawn as it gets closer to the center of the monsters body, and tapers off in size as it gets
                        //to the end. try changing the 0.5 to a higher number to see the effect.
                        scale = 1 + (0.5 * SIN(i * 35))
                        //draw the image
                        PolySprite(blob, self.tail[i].x, self.tail[i].y, scale, scale, color, 0.5, 0.5, 0, w, h)

                        //this next chunk just draws smaller dots in the center of each segment of the body
                        ALPHAMODE 0.8
                        scale = 0.1
                        PolySprite(blob, self.tail[i].x, self.tail[i].y, scale, scale, color, 0.5, 0.5, 0, w, h)
                NEXT

                //#########################
                //draw little spikes on tail
                color = RGB( 255, 255, 255 )
                //note that the x and y scales are different
                LOCAL scalex = 0.6
                LOCAL scaley = 0.1
                LOCAL rot=0
                //move the image handle to halfway down the left edge, this'll make the image
                //appear to the side of the coordinate it is drawn too, rather than the
                //center as we had for the body sections

                //rotate the 1st tail image. basically, we//re calculating the angle between
                //the last 2 points of the tail, and then adding an extra wobble (the 10*sin(time*10) bit)
                //to make the pincer type effect.
                rot = 10 * SIN(self.time * 10) + calculateAngle(self.tail[self.segments - 1].x, self.tail[self.segments - 1].y, self.tail[self.segments - 5].x, self.tail[self.segments - 5].y) + 90
                PolySprite(blob, self.tail[self.segments - 1].x, self.tail[self.segments - 1].y, scalex, scaley, color,0, 0.5, rot, w, h)

                //second tail image uses negative time to make it move in the opposite direction
                rot = 10 * SIN(-self.time * 10) + calculateAngle(self.tail[self.segments - 1].x, self.tail[self.segments - 1].y, self.tail[self.segments - 5].x, self.tail[self.segments - 5].y) + 90
                PolySprite(blob, self.tail[self.segments - 1].x, self.tail[self.segments - 1].y, scalex, scaley, color,0, 0.5, rot, w, h)



                //#####################
                //draw little fins/arms
                ALPHAMODE 1

                //begin looping through the body sections again. Note that we don't want fins
                //on the first and last section because we want other things at those coords.
                FOR i = 1 TO self.segments - 2
                        //like the bulging body, we want the fins to grow larger in the center, and smaller
                        //at the end, so the same sort of thing is used here.
                        scalex = 0.1 + (0.6 * SIN(i * 30))
                        scaley = 0.05

                        //rotate the image. We want the fins to stick out sideways from the body (the calculateangle() bit)
                        //and also to move a little on their own. the 33 * Sin(time * 5 + i * 30) makes the
                        //fin rotate based in the i index variable, so that all the fins look like they//re moving
                        //one after the other.
                        rot = 33 * SIN(self.time * 5 + i * 30) + calculateAngle(self.tail[i].x, self.tail[i].y, self.tail[i - 1].x, self.tail[i - 1].y)
                        PolySprite( blob, self.tail[i].x, self.tail[i].y, scalex, scaley, color, 0, 0.5, rot, w, h)

                        //rotate the opposte fin, note that the signs have changes (-time and -i*30)
                        //to reflect the rotations of the other fin
                        rot = 33 * SIN(-self.time * 5 - i * 30) + calculateAngle(self.tail[i].x, self.tail[i].y, self.tail[i - 1].x, self.tail[i - 1].y) + 180
                        PolySprite( blob, self.tail[i].x, self.tail[i].y, scalex, scaley, color, 0, 0.5, rot, w, h)

                NEXT

                //###################
                //Draw the eyes. These are just at 90 degrees to the head of the tail.
                color = RGB( 255, 0, 0 )
                scale = 0.6
                ALPHAMODE 0.3
                LOCAL ang# = calculateAngle(self.tail[0].x, self.tail[0].y, self.tail[1].x, self.tail[1].y)
                PolySprite(blob, self.x + (7 * COS(ang + 50)), self.y + (7 * SIN(ang + 50)), scale, scale, color, 0.5, 0.5, 0.0, w, h)
                PolySprite(blob, self.x + (7 * COS(ang + 140)), self.y + (7 * SIN(ang + 140)), scale, scale, color, 0.5, 0.5, 0.0, w, h)
                color = RGB( 255, 255, 255 )
                scale = 0.1
                ALPHAMODE 0.5
                PolySprite(blob, self.x + (7 * COS(ang + 50)), self.y + (7 * SIN(ang + 50)), scale, scale, color, 0.5, 0.5, 0.0, w, h)
                PolySprite(blob, self.x + (7 * COS(ang + 140)), self.y + (7 * SIN(ang + 140)), scale, scale, color, 0.5, 0.5, 0.0, w, h)

                //draw beaky thing
                color = RGB( 0, 200, 155 )
                scalex = 0.3
                scaley = 0.1
                ALPHAMODE 0.8
                rot = ang + 95
                PolySprite(blob, self.x, self.y, scalex, scaley, color, 0.0, 0.5, rot, w, h)

                //yellow light
                color = RGB( 255, 255, 0 )
                ALPHAMODE 0.2
                scale = 4
                PolySprite(blob, self.x, self.y, scale, scale, color, 0.5, 0.5, 0, w, h)

                //Finished!
        ENDFUNCTION

ENDTYPE

//This function calculates and returns the angle between two 2d coordinates
FUNCTION calculateAngle#:x1#,y1#,x2#,y2#
        LOCAL theX#=x1-x2
        LOCAL theY#=y1-y2
        LOCAL theAngle#=-ATAN(theX,theY)
        RETURN theAngle
ENDFUNCTION

//Draw and colorize a sprite. You can set the handle point, rotation, scale and color of the sprite
//Written by Bence Dobos
//spr - the ID of the sprite
//scalex, scaley - the ratio of the sprite scale [0.0-inf]
//color - 0xffffff is the normal color
//xc,yc - the ratio of the handle point of the sprite [0.0-1.0], this point is used to draw the sprite, rotate and scale. 0,0 is the top-left point, 0.5,0.5 is the center point
//rot - rotation of the sprite [0-360]
//w,h - width, height of the sprite in pixel, if not specified it's determined automatically
FUNCTION PolySprite: spr, x, y, scalex, scaley, color=0xffffff, xc=0.0, yc=0.0, rot=0, w=-1, h=-1
        IF w=-1
                GETSPRITESIZE spr, w, h
        ENDIF
        LOCAL w2=w*scalex
        LOCAL h2=h*scaley
        LOCAL xcenter=x+xc*w2
        LOCAL ycenter=y+yc*h2
        LOCAL xr1=-xc*w2
        LOCAL yr1=-yc*h2
        LOCAL xr2=(1.0-xc)*w2
        LOCAL yr2=-yc*h2
        LOCAL xr3=(1.0-xc)*w2
        LOCAL yr3=(1.0-yc)*h2
        LOCAL xr4=-xc*w2
        LOCAL yr4=(1.0-yc)*h2

        LOCAL x1, y1, x2, y2
        LOCAL x3, y3, x4, y4
        IF rot<>0
                LOCAL sp = SIN(rot)
                LOCAL cp = COS(rot)
                x1 = xr1*cp-yr1*sp+x
                y1 = xr1*sp+yr1*cp+y
                x2 = xr2*cp-yr2*sp+x
                y2 = xr2*sp+yr2*cp+y
                x3 = xr3*cp-yr3*sp+x
                y3 = xr3*sp+yr3*cp+y
                x4 = xr4*cp-yr4*sp+x
                y4 = xr4*sp+yr4*cp+y
        ELSE
                x1=xr1+x
                y1=yr1+y
                x2=xr2+x
                y2=yr2+y
                x3=xr3+x
                y3=yr3+y
                x4=xr4+x
                y4=yr4+y
        ENDIF

         STARTPOLY spr
          POLYVECTOR   x1, y1,  0,  0, color
          POLYVECTOR   x2, y2,  0,  h, color
          POLYVECTOR   x3, y3,  w,  h, color
          POLYVECTOR   x4, y4,  w,  0, color
         ENDPOLY
ENDFUNCTION
 

Edit: Missing beaky thing, fixed.

[attachment deleted by admin]
« Last Edit: 2011-Feb-11 by Albert »

Offline Wampus

  • Prof. Inline
  • *****
  • Posts: 1004
    • View Profile
Re: Blobmonster
« Reply #1 on: 2011-Feb-10 »
Heheh. Cute.

Offline Albert

  • Dr. Type
  • ****
  • Posts: 257
    • View Profile
    • Blog
Re: Blobmonster
« Reply #2 on: 2011-Feb-10 »
Cute? See in motion. I have nithmares with it.  :O

Offline Slydog

  • Prof. Inline
  • *****
  • Posts: 930
  • KodeSource
    • View Profile
    • KodeSource
Re: Blobmonster
« Reply #3 on: 2011-Feb-10 »
Very cool effect!  :good:

It would look great in a game.
Or to apply to a caterpillar animation.  (By using some of the code of course, everything but the drawing I guess!)
It's neat how the only external graphic is the 'blob' circle and how it's used to create the creature part by part.
My current project (WIP) :: TwistedMaze <<  [Updated: 2015-11-25]

Offline DmitryK

  • Mc. Print
  • *
  • Posts: 44
  • ......................................
    • View Profile
    • DK's mobile games
Re: Blobmonster
« Reply #4 on: 2011-Feb-10 »
wow super effect  :blink:
Our life is just a Game!

Offline Ian Price

  • Administrator
  • Prof. Inline
  • *******
  • Posts: 4144
  • On the shoulders of giants.
    • View Profile
    • My Apps
Re: Blobmonster
« Reply #5 on: 2011-Feb-11 »
That is wonderfully organic. Clever stuff. :)
I came. I saw. I played.

Offline Wampus

  • Prof. Inline
  • *****
  • Posts: 1004
    • View Profile
Re: Blobmonster
« Reply #6 on: 2011-Feb-11 »
That is wonderfully organic. Clever stuff. :)

Yeah, organic it is. Even when it twists in reversals or half reversals it is very life-like.

Stuff like this would be great in a rehash of the first level of Spore. That was the most fun part of that game imo.

Offline Albert

  • Dr. Type
  • ****
  • Posts: 257
    • View Profile
    • Blog
Re: Blobmonster
« Reply #7 on: 2011-Feb-11 »
The beak beetween its two eye was missing. I added it and changed the first post.

Offline Hark0

  • Prof. Inline
  • *****
  • Posts: 1020
  • Geek Developer
    • View Profile
    • LitioPixel - Desarrollo de videojuegos con GLBasic | Videogame development with GLBasic
Re: Blobmonster
« Reply #8 on: 2011-Feb-11 »
VERY GOOD!!!

 :good:
http://litiopixel.blogspot.com
litiopixel.blogspot.com - Desarrollo videojuegos Indie · Pixel-Art · Retroinformática · Electrónica Development Indie Videogames · Pixel-Art · Retrocomputing · Electronic

Offline Leginus

  • Dr. Type
  • ****
  • Posts: 288
    • View Profile
Re: Blobmonster
« Reply #9 on: 2011-Feb-11 »
Wow!  Thats a really nice routine. Wish i had paid more attention to maths at school MANY MANY years ago :)

Offline Moebius

  • Dr. Type
  • ****
  • Posts: 315
    • View Profile
Re: Blobmonster
« Reply #10 on: 2011-Feb-12 »
Very nice!
Endless Loop: n., see Loop, Endless.
Loop, Endless: n., see Endless Loop.
- Random Shack Data Processing Dictionary

Offline aonyn

  • Mr. Polyvector
  • ***
  • Posts: 136
    • View Profile
Re: Blobmonster
« Reply #11 on: 2011-Feb-15 »
Wow, that is really very cool.  ;)
For by grace are ye saved through faith, and that not of yourselves: it is the gift of God: Not of works, lest any man should boast. -Ephesians 2:8-9

Offline Schranz0r

  • Premium User :)
  • Administrator
  • Prof. Inline
  • *******
  • Posts: 5014
  • O Rly?
    • View Profile
Re: Blobmonster
« Reply #12 on: 2011-Feb-15 »
I like that style!
I <3 DGArray's :D

PC:
AMD RYzen 7 1700 @3.9Ghz, 16GB HyperX Fury 2666Mhz Ram, ASUS ROG GTX 1060 STRIX 6GB, Windows 10 Pro 64Bit, MSi Tomahawk B350 Mainboard

Offline phaelax

  • Mc. Print
  • *
  • Posts: 36
    • View Profile
Re: Blobmonster
« Reply #13 on: 2011-Feb-16 »
I really need to find a way to work that creature into a game

Offline Albert

  • Dr. Type
  • ****
  • Posts: 257
    • View Profile
    • Blog
Re: Blobmonster
« Reply #14 on: 2011-Feb-16 »
You are free to do it, just told to Charlie :) He wants to see what games are we make with his monsters: http://www.charliesgames.com/wordpress/?p=441