⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 sporen.jc

📁 JILRuntime A general purpose, register based virtual machine (VM) that supports object-oriented feat
💻 JC
字号:

//------------------------------------------------------------------------------
// sporen.jc
//------------------------------------------------------------------------------
//
// An applet for the ScriptApp application, based on my life simulation
// algorithm "Sporen".
// To run this script, simply drag it onto the ScriptApp's icon.
//
//------------------------------------------------------------------------------

import stdlib;
import Screen;
import RectLayer;

//------------------------------------------------------------------------------
// forward declarations
//------------------------------------------------------------------------------

class World;
class Spore;
class Color;

//------------------------------------------------------------------------------
// class SporeApplet
//------------------------------------------------------------------------------

class SporeApplet : interface Applet
{
	method				SporeApplet	(Screen&);
	method				OnOpen		();
	method				OnClose		();
	method				OnClick		(long button, long x, long y);
	method				OnKey		(long key);
	method				Idle		();
	method				Init		();

	Screen&				m_Screen;
	World&				m_World;
	long				m_Inited;
	long				m_Timer;
}

//------------------------------------------------------------------------------
// class World
//------------------------------------------------------------------------------
// The World is a two dimensional array where the Spores live.
// This class uses the built-in array to create a two-dimensional array.

class World
{
	method 				World		(long width, long height);
	method long			Life		();
	method 				PlaceSpore	(long x, long y, Spore& s );
	method 				RemoveSpore	(long x, long y);
	method const Spore& GetSpore	(long x, long y);
	method				Wrap		(long& x, long& y);

	long				dimX;
	long				dimY;
	long				updateY;
	array&				matrix;
}

//------------------------------------------------------------------------------
// class Spore
//------------------------------------------------------------------------------
// A spore has a fixed life-cycle: It gets born into a cell, eats one or more of it's neighbors,
// reproduces itself to into a free cell next to it, and eventually dies.

class Spore
{
	method				Spore		(const Color& c, long s);
	method				Spore		(const Spore& dad);
	method				Life		();
	method				SpinToXY	(long& x, long& y);

	long				energy;		// decreases continually, if 0, it dies
	long				x;			// position in matrix
	long				y;			// position in matrix
	Color				color;		// color of the spore
	long				shape;		// "family" of the spore
	long				spin;		// direction of the spore
}

//------------------------------------------------------------------------------
// class Cell
//------------------------------------------------------------------------------
// A simple data class that stores a reference to a Spore and a RectLayer, which
// is used to display the cell on the screen.

class Cell
{
	method				Cell		(long x, long y);
	method				Update		();

	var&				spore;
	RectLayer&			layer;
}

//------------------------------------------------------------------------------
// class Color
//------------------------------------------------------------------------------
// Simple data class that stores an RGB value.

class Color
{
	long r, g, b;
	method Color(long red, long green, long blue) { r = red; g = green; b = blue; }
}

//------------------------------------------------------------------------------
// global variables and constants
//------------------------------------------------------------------------------

const long kEnergyDec			= 1;	// defines how fast spore grows old (and dies)
const long kEatBonus			= 49;	// how much energy eating brings
const long kReproCost			= 1;	// how much energy reproduction costs
const long kEatLevel			= 36;	// level at which spore starts to eat
const long kReproLevel			= 71;	// level at which spore starts to reproduce
const long kCellSize			= 8;	// width and height of a cell in pixel
const long kUpdateTime			= 50;	// update interval in msec
const long kUpdateRowsPerIdle	= 60;	// update 60 rows at once

const Color& kBackColor = new Color(0, 0, 0);

//------------------------------------------------------------------------------
// global reference to our applet
//------------------------------------------------------------------------------
// This allows us to store a reference to our applet as a global variable.
// Several classes need access to our applet, and this is the most convenient
// way to do it.

var& g_Applet = null;	// Only type 'var' allows us to do this...

//------------------------------------------------------------------------------
// function CreateApplet
//------------------------------------------------------------------------------
// The Application calls this function to create our applet.
// We need to implement this function and return an instance of our applet.

function Applet& CreateApplet(Screen& screen)
{
	g_Applet = new SporeApplet( screen );
	return g_Applet;
}

//------------------------------------------------------------------------------
// class SporeApplet
//------------------------------------------------------------------------------
// constructor

method SporeApplet::SporeApplet(Screen& screen)
{
	// store reference to screen
	m_Screen = screen;

	// set fixed size
	m_Screen.FixedSize( 640, 480 );

	// set background color
	m_Screen.BackColor( kBackColor.r, kBackColor.g, kBackColor.b );

	// init members
	m_Inited = false;
	m_Timer = 0;

	// allocate a world
	m_World = new World( 80, 60 );

	// init random generator
	stdlib::RandInit();
}

//------------------------------------------------------------------------------
// OnOpen
//------------------------------------------------------------------------------
//

method SporeApplet::OnOpen()
{
	// add all Cell layers to our Screen object
	for( long y = 0; y < m_World.dimY; y++ )
	{
		for( long x = 0; x < m_World.dimX; x++ )
		{
			Cell& cell = m_World.matrix[y][x];
			m_Screen.AddLayer( cell.layer );
		}
	}
}

//------------------------------------------------------------------------------
// OnClose
//------------------------------------------------------------------------------
//

method SporeApplet::OnClose()
{
	m_Screen.RemoveAllLayers();
}

//------------------------------------------------------------------------------
// OnClick
//------------------------------------------------------------------------------
//

method SporeApplet::OnClick(long button, long x, long y)
{
}

//------------------------------------------------------------------------------
// OnKey
//------------------------------------------------------------------------------
//

method SporeApplet::OnKey(long key)
{
}

//------------------------------------------------------------------------------
// Idle
//------------------------------------------------------------------------------
//

method SporeApplet::Idle()
{
	if( not m_Inited )
	{
		Init();
	}
	m_World.Life();
	if( m_Timer < stdlib::GetTicks() )
	{
		m_Timer = stdlib::GetTicks() + kUpdateTime;
		m_Screen.Redraw();
	}
}

//------------------------------------------------------------------------------
// Init
//------------------------------------------------------------------------------
//

method SporeApplet::Init()
{
	// create some colors
	Color blue  = new Color( 64, 64,255);
	Color red   = new Color(255, 64,64 );
	Color green = new Color( 64,255,64 );
	Color yello = new Color(255,255,64 );

	// place four spores of different colors and shape as start population
	m_World.PlaceSpore( 39, 29, new Spore(blue,  1) );
	m_World.PlaceSpore( 40, 29, new Spore(red,   2) );
	m_World.PlaceSpore( 39, 30, new Spore(green, 3) );
	m_World.PlaceSpore( 40, 30, new Spore(yello, 4) );

	m_Inited = true;
}

//------------------------------------------------------------------------------
// class World
//------------------------------------------------------------------------------
// Implementation

method World::World(long width, long height)
{
	dimX = width;
	dimY = height;
	updateY = 0;
	matrix = new array[height];
	for( long y = 0; y < height; y++ )
	{
		matrix[y] = new array[width];
		for( long x = 0; x < width; x++ )
		{
			matrix[y][x] = new Cell(x, y);
		}
	}
}

//------------------------------------------------------------------------------
// Life
//------------------------------------------------------------------------------
// Call Life() of all Spores in this world

method long World::Life()
{
	long allDead = true;
	long y = updateY;
	updateY += kUpdateRowsPerIdle;
	if( updateY > dimY )
		updateY = dimY;
	for( ; y < updateY; y++ )
	{
		for( long x = 0; x < dimX; x++ )
		{
			Cell& cell = matrix[y][x];
			Spore& spore = cell.spore;
			if( spore != null )
			{
				spore.Life();
				cell.Update();
				allDead = false;
			}
		}
	}
	if( updateY == dimY )
		updateY = 0;
	return allDead;
}

//------------------------------------------------------------------------------
// PlaceSpore
//------------------------------------------------------------------------------
// Place a Spore in the world

method World::PlaceSpore(long x, long y, Spore& s)
{
	Cell& cell = matrix[y][x];
	Color& c = s.color;
	cell.layer.SetColor( c.r, c.g, c.b );
	cell.layer.Show();
	cell.spore = s;
	s.x = x;
	s.y = y;
}

//------------------------------------------------------------------------------
// RemoveSpore
//------------------------------------------------------------------------------
// Remove a Spore from the world

method World::RemoveSpore(long x, long y)
{
	Cell& cell = matrix[y][x];
	cell.layer.Hide();
	cell.spore = null;
}

//------------------------------------------------------------------------------
// GetSpore
//------------------------------------------------------------------------------
// Check if a cell contains a Spore and return it

method const Spore& World::GetSpore(long x, long y)
{
	Cell& cell = matrix[y][x];
	return cell.spore;
}

//------------------------------------------------------------------------------
// Wrap
//------------------------------------------------------------------------------
// Wrap around coords

method World::Wrap(long& x, long& y)
{
	if( x < 0 )
		x += dimX;
	else if( x >= dimX )
		x -= dimX;
	if( y < 0 )
		y += dimY;
	else if( y >= dimY )
		y -= dimY;
}

//------------------------------------------------------------------------------
// class Cell
//------------------------------------------------------------------------------
// Constructor

method Cell::Cell(long x, long y)
{
	spore = null;
	layer = new RectLayer();
	layer.ResizeTo( kCellSize - 1, kCellSize - 1 );
	layer.MoveTo( x * kCellSize, y * kCellSize );
}

//------------------------------------------------------------------------------
// Update
//------------------------------------------------------------------------------
//

method Cell::Update()
{
	Spore& s = spore;
	if( s != null )
	{
		long e = s.energy;
		Color& c = s.color;
		long r = c.r * e / 100;
		long g = c.g * e / 100;
		long b = c.b * e / 100;
		layer.SetColor(r, g, b);
	}
}

//------------------------------------------------------------------------------
// class Spore
//------------------------------------------------------------------------------
// Constructor

method Spore::Spore(const Color& c, long s)
{
	energy = 100;
	x = 0;
	y = 0;
	color = c;
	shape = s;
	spin = stdlib::Rand(0, 7);
}

//------------------------------------------------------------------------------
// class Spore
//------------------------------------------------------------------------------
// copy constructor

method Spore::Spore(const Spore& dad)
{
	energy = dad.energy * 81 / 100;
	x = 0;
	y = 0;
	color = dad.color;
	shape = dad.shape;
	spin = dad.spin;
}

//------------------------------------------------------------------------------
// Life
//------------------------------------------------------------------------------
// Simulate the Spores life

method Spore::Life()
{
	long sporX = 0;
	long sporY = 0;
	World& world = g_Applet.SporeApplet::m_World;

	energy -= kEnergyDec;
	if( energy <= 0 )
	{
		// spore is dead, remove from world
		world.RemoveSpore( x, y );
		return;
	}
	if( energy < kEatLevel )
	{
		// peek around to find something to eat...
		SpinToXY(sporX, sporY);
		world.Wrap(sporX, sporY);
		// get the spore from the cell
		const Spore& enemy = world.GetSpore(sporX, sporY);
		// only eat if it's from other family
		if( enemy != null )
		{
			// found a meal?
			if( enemy.shape != shape )
			{
				// yum!
				world.RemoveSpore( sporX, sporY );
				energy += kEatBonus;
				if( energy > 100 )
					energy = 100;
			}
		}
	}
	else if( energy >= kReproLevel )
	{
		// peek around to find a free place
		SpinToXY(sporX, sporY);
		world.Wrap(sporX, sporY);
		// found a spot?
		if( world.GetSpore(sporX, sporY) == null )
		{
			// place kid in cell
			world.PlaceSpore( sporX, sporY, new Spore(this) );	// kid inherits from us
			energy -= kReproCost;
			if( energy < 0 )
				energy = 0;
		}
	}
	if( ++spin > 7 )
		spin = 0;
}

//------------------------------------------------------------------------------
// SpinToXY
//------------------------------------------------------------------------------
// Computes cell coords from the spin index

method Spore::SpinToXY(long& nx, long& ny)
{
	long s = spin;
	if( s >= 4 )
		s++;
	nx = x + s % 3 - 1;
	ny = y + s / 3 - 1;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -