Bu Konuyu Okuyanlar: 1 ZiyaretÇi
Cevapla 
 
Değerlendir:
  • 0 Oy - 0 Yüzde
  • 1
  • 2
  • 3
  • 4
  • 5
Microsoft Terrarium
03-12-2010, 10:25 AM
Mesaj: #1
Microsoft Terrarium
Kaynak:

Guests cannot see links in the messages. Please register to forum by clicking href="member.php?action=register">here to see links.
Guests cannot see links in the messages. Please register to forum by clicking href="member.php?action=register">here to see links.
Guests cannot see links in the messages. Please register to forum by clicking href="member.php?action=register">here to see links.
Guests cannot see links in the messages. Please register to forum by clicking href="member.php?action=register">here to see links.


Microsoft Terrarium

Merbalar, yine ilginç bir yazı dizisine başlıyoruz, "Microsoft Terrarium". Yazılarımızda Microsoft'un .Net Frameworkun bütün nimetlerinden yararlanarak hazırladığı oyunu olan Microsoft Terrarium'u yakından tanıyacağız. Serinin bu ilk yazısı aslında özet mahiyetinde. Terrarium'un bütün özelliklerine "şöyle bir" bakıyoruz. Serinin diğer yazılarında ise oyunun altyapı, grafiksel arayüz, networking, code access security gibi yönlerini daha detaylı olarak inceleyeceğiz.

Yazar: Suphi UÇAR
Yazıldığı Tarih: 01.03.2004



Bilgisayar oyunlarıyla yakından ilgiliyseniz veya sıkı bir bilgisayar ve özellikle .Net aşığıysanız Terrarium kelimesini kesinlikle biryerlerden duymuşsunuzdur. İlk karşılaşıldığında kulağa gayet yabancı gelen bu kelime, bize içinde küçük kara hayvanlarının - örümcek, tırtıl, kertenkele, böceklerin - yaşadığı, genellikle cam bir muhafaza ile çevrelenmiş ortamı anlatıyor. Bir nevi akvaryumun suyunun boşaltılıp içinde böcek beslenen hali denebilir. Balıkların güzelliği ve bir akvaryumun dinlendiriciliği dururken böceklerle uğraşmak neden diyebilirsiniz ama bence Terrarium la tanıştıktan sonra fikirleriniz değişecek.


Microsoft yeni programlama ortamı olan .Net Framework’ü kullanıcılara tanıtırken, pek alışılmamış bir karar alarak .Net Framework’ün önemli özelliklerini kullanan, ilgi çekiçi bir uygulama geliştirmiş ve ortaya Terarium çıkmış. Terrarium .Net Framework’un getirdiği birçok yeniliği bir arada görebileceğiniz çok kullanıcılı bir ekosistem simülasyonu. Bu yenilikleri şöyle sıralayabiliriz;


daha etkileyici kullanıcı arayüzleri tasarlamak için kullanılan Windows Formları-DirectX entegrasyonu,

· XML Web servisleri,

· peer-to-peer networking desteği,

· aynı uygulamada birden fazla programlama dili kullanma avantajı,

· code access security altyapısı ile kullanıcılar arasında transfer edilen program parçalarının güvenli bir şekilde çalıştırılması



Terrarium’u tam bir oyun olarak tanımlamak doğru olmaz. Çünkü oyunun başkahramanı olan hayvanları kullanıcı yaratıyor. Kullanıcı kendi hayvanının “kodunu” kendisi yazıyor. Derlenen etobur, otobur veya bitki programının çıktısı(dll) oyuna tanıtılıyor. Bu şekilde kendi yarattığınız hayvanınız veya bitkiniz Terrarium’a dahil oluyor. Terrarium’u sıradan bir oyun olmaktan kurtaran en önemli özellik bu bence. Hem çok zevkli bir oyun oynayıp hem de .Net’in yeni özelliklerini keşfediyorsunuz.


Terrarium’u Guests cannot see links in the messages. Please register to forum by clicking href="member.php?action=register">here to see links. adresinden indirebilirsiniz. Kurulumdan önce bilgisayarınızda .Net Framework’un varlığından emin olun. Oyuna başlamadan önce sitedeki tutorial’ı okumanızı tavsiye ederim. Buradan kurulum ile ilgili bilgilere, kullanıcı arayüzünün kullanımına, sıkca sorulan sorular’a ve hatta örnek bir otobur koduna erişebilirsiniz. Gerçek bir “Terrarium Kurdu“ olmak içinse Advanced Developer Guide ve Object Model dökümanları mutlaka okunmalı.


Terrarium’a dahil edilen canlıları kullanıcının kodladığından bahsetmiştim. Bitkinizi veya böceğinizi yaratmak C# veya VB .NET dillerinden birini kullanabilirsiniz. Bitkileri kodlamak gayet kolay ama otobur ve etobur kodlayacaksanız internette kolaylıkla bulabileceğiniz kodları incelemenizi tavsiye ederim. Mevcut kodları inceleyerek bir canlının temel özelliklerini, görünümünü, familyasına ait karakteristik özellikleri ve hatta genetik altyapısını nasıl oluşturabileceğiniz hakkında fikir sahibi olabilirsiniz. Kodlamaya alıştıkça siz de yeni arama algoritma geliştirerek yiyecek bulma, tehlikelerden korunma, mutasyon gibi canlınızın zor koşullarda daha kolay hayatta kalmasını sağlayacak yöntemler keşfedeceksiniz.


Terrarium iki modda çalışabiliyor: teraryum ve ekosistem. Eğer teraryum modda oynuyorsanız internete çıkmadan kendi bilgisayarınızda, kendi yarattığınız hayvanlarla oyunu oynayabiliyorsunuz. Gerçek eğlence için ise ekosistem moduna geçmeniz gerekiyor. Ekosistem modunda oyun P2P Terrarium Network’e bağlanıyor. Ana Terraium sunucusu sizi IP adresinizden tanıdığı için statik bir IPye sahip olmanız gerekiyor. Bir proxy arkasındaysanız veya internete çıkarken Network Address Translation’a maruz kalıyorsanız şimdilik ekosistem modda oynayamıyacaksınız demektir. Eğer bu duruma uygun bir IP’niz varsa ana Terrium sunucusu sizi peer listesine kaydediyor. Ardından 20-30 kullanıcılık, coğrafi olarak birbirine yakın peerlardan oluşan, bir peer listesi çıkarıyor ve sizi bu listedeki kullanıcılarla bir oyuna dahil ediyor. Teraryum modda denediğiniz etobur ve otoburlarınız artık daha vahşi bir doğada diğer kullanıcıların hayvanlarıyla mücadele etmek zorunda kalıyor.




Burada oyunun önemli bir özelliğinden sözetmek gerekiyor. Daha önce bahsettiğim 20-30 kişilik ekosistem takımındaki kullanıcılar aynı ekranı görmüyorlar. Her kullanıcı eko sistemin bir parçasını görüyor. Hayvanların bu ekosistem parçaları arasındaki geçişini ise teleporter adı verilen bir obje yapıyor. Teleporter oyun süresince çevrede dolaşan mavi, içinde şimşekler çakan bir küre. Teraryum modda oynarken teleporter kendisine değer herşeyi başka bir noktaya ışınlıyor. Ekosistem modda ise objeleri aynı ekosistem içindeki rastgele bir peer’a gönderiyor. Yani oyunu oynarken sizin oyun takımınızdaki başka bir peer’dan sizin ekranınıza aniden bir hayvan ışınlanabiliyor.


Terrarium’u oynamak göründüğü kadar basit değil ama kendinizi oyuna kaptırınca saatlerce başından kalkamıyorsunuz. Yaratacağınız canlının daha dayanıklı, şartlara daha kolay alışabilmesi için kodları defalarca değiştiriyorsunuz, aslında yapmanız gereken tek şey böcek gibi düşünmek.

Yazar : Suphi UÇAR
e-Posta : suphiucar@msakademik.net

Özdemir Şarman
aka (Charmant-zavanetratan)
Web Sayfasını Ziyeret Edin Tüm Mesajlarını Bul
Alıntı Yaparak Cevapla
03-12-2010, 10:27 AM
Mesaj: #2
Whooper01
Kod:
//***Importing of NameSpaces
using System;
using System.Drawing;
using System.Collections;
using System.IO;
//***end importing

//***Creature Definition
[assembly: OrganismClass("WHOOPER01")] // The class that derives from Creature
[assembly: AuthorInformation("Jeremy C. Wright", "jwright@tacf.org")] // Your Email
[CarnivoreAttribute(false)] // It's an herbivore

// Define what the beast is
[AnimalSkin("Beetle")]
[MarkingColor(KnownColor.Green)]
[MatureSize(26)] // Medium sized so it doesn't get too slow in old age

// Point Based Attributes
// You get 100 points to distribute among these attributes to define
// what your organism can do. Choose them based on the strategy your organism
// will use
[MaximumEnergyPoints(20)] // Needs a little energy to reproduce
[EatingSpeedPoints(0)] // Who cares how long it takes to eat
[AttackDamagePoints(0)] // Doesn't ever attack
[DefendDamagePoints(0)] // Runs too fast to need to defend
[MaximumSpeedPoints(40)] // Sprinter baby!
[CamouflagePoints(0)] // Camo is crap anyways
[EyesightPoints(40)] // Need this to find plants better
//*** end definition

public class WHOOPER01 : Animal
{

//*** global attributes
PlantState targetPlant = null; // The current plant we're going after
AnimalState attackerAnimal = null; // The current attacker we are fleeing
const int cruisingSpeed = 5; // When there's nothing better to do: dawdle
const int fleeingSpeed = 40; // Running from scary crap speed
private Point parentLocation; // For the BornEvent method
int aroundCount=0; // Used to make semi-intelligent "move around"
// decisions (don't change)
// Species counter variables
protected int mcKilled;
protected int mcBorn;
protected int mcTeleported;
//***end global attributes

//***event calls
// Set up any event handlers that we want when first initialized
protected override void Initialize()
{
Load += new LoadEventHandler(LoadEvent);
Idle += new IdleEventHandler(IdleEvent);
Attacked += new AttackedEventHandler(AttackedEvent);
Born += new BornEventHandler(BornEvent);
MoveCompleted += new MoveCompletedEventHandler(MoveCompletedEvent);
Teleported += new TeleportedEventHandler(TeleportedEvent);
AttackCompleted += new AttackCompletedEventHandler(AttackCompletedEvent);
//EatCompleted += new EatCompletedEventHandler(EatCompletedEvent);
ReproduceCompleted += new ReproduceCompletedEventHandler(ReproduceCompletedEvent);
}
//***end event calls

//***event definitions
// Fired if we arrived at our destination or got blocked
void MoveCompletedEvent(object sender, MoveCompletedEventArgs e)
{
if(e.Reason == ReasonForStop.Blocked)
{
if(targetPlant != null || attackerAnimal != null)
{
// If we get blocked, try moving perpendicular 3 times,
// then find other target
if(aroundCount < 3)
{
Point originalDestination = e.MoveToAction.MovementVector.Destination;
Vector originalVector = Vector.Subtract(originalDestination, this.Position);
Vector newVector = originalVector.Rotate(Math.PI / 4);
Vector unitVector = newVector.GetUnitVector();
Vector newPositionVector = unitVector.Scale(20);
Point newPosition = Vector.Add(Position, newPositionVector);
aroundCount += 1;
WriteTrace("Tried going around " + aroundCount + " times.");
if (attackerAnimal != null)
BeginMoving(new MovementVector(newPosition, fleeingSpeed));
else
BeginMoving(new MovementVector(newPosition, cruisingSpeed));
}
else
{
WriteTrace("Going Around failed, getting new target");
BeginMoving(getDestination());
}

}
}
}

private void BornEvent(object sender, BornEventArgs e)
{
byte[] dna = e.Dna;
if ( dna != null )
{
MemoryStream m = new MemoryStream(dna);
BinaryReader b = new BinaryReader(m);
parentLocation = new Point(b.ReadInt32(),b.ReadInt32());
BeginMoving(new MovementVector(parentLocation, getSpeed()));
b.Close();
}
}

// First event fired on an organism each turn
void LoadEvent(object sender, LoadEventArgs e)
{
try
{
if(targetPlant != null)
{
// See if our target plant still exists (it may have died)
// LookFor returns null if it isn't found
targetPlant = (PlantState) LookFor(targetPlant);
if(targetPlant == null)
WriteTrace("Target plant disappeared.");
}
if (Antennas.AntennaValue!=6)
{
Antennas.AntennaValue=6;
}
}
catch(Exception exc)
{
WriteTrace(exc.ToString());
}
}

// Fired if we are being attacked
void AttackedEvent(object sender, AttackedEventArgs e)
{
if(e.Attacker.IsAlive)
{
AnimalState TheAttacker = e.Attacker;
BeginDefending(TheAttacker); //defend against the attacker
WriteTrace("Run away to some random point");
BeginMoving(getDestination());
}
}

// Species Counter function
public void AttackCompletedEvent(object sender, AttackCompletedEventArgs e)
{
if ( e.Killed )
{
mcKilled += 1;
WriteTrace("TO-O-O-O..."); // Doesn't work without this line
}
}

// Species Counter function
public void TeleportedEvent(object sender, TeleportedEventArgs e)
{
mcTeleported += 1;
targetPlant = null;
attackerAnimal = null;
}

// Species Counter function
public void ReproduceCompletedEvent(object sender, ReproduceCompletedEventArgs e)
{
mcBorn += 1;
}

// Fired after all other events are fired during a turn
void IdleEvent(object sender, IdleEventArgs e)
{
try
{
// Reproduce as often as possible
if(CanReproduce)
{
// Writing parents location for child
MemoryStream m = new MemoryStream();
BinaryWriter b = new BinaryWriter(m);
b.Write(Position.X);
b.Write(Position.Y);
BeginReproduction(m.ToArray());
b.Close();
}
// Scan for potential attackers
if (ScanForAttackers())
{
return;
}
// If we can eat and we have a target plant, eat
if(CanEat)
{
WriteTrace("I can eat");
if(!IsEating)
{
WriteTrace("I'm not eating... Target plant?");
if(targetPlant != null)
{
WriteTrace("Target plant found, is healthy?");
// Only accept if plant is healthy (unless we are starving)
if (targetPlant.PercentInjured < 0.7 || State.EnergyState == EnergyState.Deterioration)
{
WriteTrace("Healthy, can I reach it?");
if(WithinEatingRange(targetPlant))
{
WriteTrace("Within Range, Start eating.");
BeginEating(targetPlant);
if(IsMoving)
{
WriteTrace("Stop while eating.");
StopMoving();
}
}
else
{
if(!IsMoving)
{
WriteTrace("Move to Target Plant");
BeginMoving(new MovementVector(targetPlant.Position, 2));
}
}
}
}
else
{
WriteTrace("Don't have target plant.");
if(!ScanForTargetPlant())
if(!IsMoving)
{
WriteTrace("No plant found, so pick a random point and move there");
/*
int RandomX= OrganismRandom.Next(0, WorldWidth - 1);
int RandomY= OrganismRandom.Next(0, WorldHeight - 1);
BeginMoving(new MovementVector(new Point(RandomX,RandomY), 2));
*/
BeginMoving(getDestination());
}
else
{
WriteTrace("Moving and Looking...");
}
}
}
else
{
WriteTrace("Eating.");
if(IsMoving)
{
WriteTrace("Stop moving while eating.");
StopMoving();
}
}
}
else
{
WriteTrace("Full: do nothing.");
if(IsMoving)
StopMoving();
}
}
catch(Exception exc)
{
WriteTrace(exc.ToString());
}
}
//***end event definitions

//***generic functions/methods
// If you ever need to just re-insure your target is valid
void RefreshTarget()
{
if ( targetPlant == null )
{
return;
}
PlantState newState = (PlantState) LookFor(targetPlant);
if(newState != null)
{
targetPlant = newState;
}
else
{
targetPlant = null;
}
}

// Generic "are there attackers around I should run from" method
bool ScanForAttackers()
{
try
{
ArrayList foundAnimals = Scan();
if(foundAnimals.Count > 0)
{
foreach(OrganismState organismState in foundAnimals)
{
if(organismState is AnimalState)
{
IAnimalSpecies iAS = (IAnimalSpecies) organismState.Species;
if (iAS.IsCarnivore)
{
if (WithinAttackingRange ((AnimalState)organismState))
{
WriteTrace("Carnivore in range: fleeing");
attackerAnimal = (AnimalState) organismState;
Vector newVector = Vector.Subtract(organismState.Position, Position);
Vector newPositionVector = newVector.Scale(10);
Point newPosition = Vector.Add(Position, newPositionVector);
BeginMoving(new MovementVector(newPosition, fleeingSpeed));
return true;
}
}
}
}
}
}
catch(Exception exc)
{
WriteTrace(exc.ToString());
}
attackerAnimal = null;
return false;
}

// sets speed based upon current energy level
int getSpeed()
{
int speed = 0;
switch(State.EnergyState)
{
case EnergyState.Full:
speed = Convert.ToInt32(Species.MaximumSpeed * .7); // 70% speed
break;
case EnergyState.Normal:
speed = Convert.ToInt32(Species.MaximumSpeed * .5); // 50% speed
break;
case EnergyState.Hungry:
speed = Convert.ToInt32(Species.MaximumSpeed * .40); // 40% speed
break;
default:
speed = Convert.ToInt32(Species.MaximumSpeed * .25); // 25% speed
break;
}
return speed;
}

// Global 'bit' to set a destination based upon a variety of factors
MovementVector getDestination()
{
// sets destination as a random point
MovementVector destination = new MovementVector(
new Point (
OrganismRandom.Next(0, WorldWidth - 1),
OrganismRandom.Next(0, WorldHeight - 1)
),getSpeed());
return destination;
}

// Used to find closest plant from an array of plants
bool FindClosestPlant(ArrayList plants)
{
// we are assuming that plants is already set to an ArrayList of plants
double minDistance = double.MaxValue;
PlantState target = null;

if ( plants.Count > 0 )
{
foreach(PlantState plant in plants)
{
if (DistanceTo(plant) < minDistance && (plant.PercentInjured < 75 || (State.EnergyState == EnergyState.Deterioration)))
{
target = plant;
minDistance = DistanceTo(plant);
}
}
}
return true;
}

// Looks for target plants, and starts moving towards the first one it finds
bool ScanForTargetPlant()
{
try
{
ArrayList foundCreatures = Scan();
if(foundCreatures.Count > 0)
{
// Always move after closest plant or defend closest creature if there is one
foreach(OrganismState organismState in foundCreatures)
{
if(organismState is PlantState)
{
targetPlant = (PlantState) organismState;
BeginMoving(new MovementVector(organismState.Position, 2));
return true;
}
}
}
}
catch(Exception exc)
{
WriteTrace(exc.ToString());
}
return false;
}
//***end generic functions/methods

//***species counter bits
// Species Counter function output
protected void TraceState()
{
if ( State.IsMature )
{
WriteTrace("+/" + State.IncubationTicks + "/" + State.ReproductionWait);
}
else
{
WriteTrace("-/" + State.Radius + "/" + State.GrowthWait + " == " + GetPercentUsedTicks(State).ToString("n"));
}
WriteTrace(mcKilled + "/" + mcBorn + "/" + mcTeleported + "/" + State.Generation);
WriteTrace(State.PercentLifespanRemaining.ToString("n") + "/" + State.PercentEnergy.ToString("n") + "/" + State.PercentInjured.ToString("n"));
}

// Above uses those functions:
public static double GetPercentUsedTicks (AnimalState animal)
{
return (double)GetUsedTicks(animal) / animal.TickAge;
}

public static int GetUsedTicks (AnimalState animal)
{
int usedTicks = animal.Species.GrowthWait * ( animal.Radius - 11 ) +
animal.Species.GrowthWait - animal.GrowthWait;
return usedTicks;
}
//***end Species Counter bits

//***serialize/deserialize bits
// This gets called whenever your creature is being saved -- either the game is closing
// or you are being teleported. Store anything you want to remember when you are
// instantiated again in the stream.
public override void SerializeAnimal(MemoryStream m)
{
BinaryWriter b = new BinaryWriter(m);
b.Write(mcKilled);
b.Write(mcBorn);
b.Write(mcTeleported);
}

// This gets called when you are instantiated again after being saved. You get a
// chance to pull out any information that you put into the stream when you were saved
public override void DeserializeAnimal(MemoryStream m)
{
BinaryReader b = new BinaryReader(m);
mcKilled = b.ReadInt32();
mcBorn = b.ReadInt32();
mcTeleported = b.ReadInt32();
}
//***end serialize/deserialize bits
}

Özdemir Şarman
aka (Charmant-zavanetratan)
Web Sayfasını Ziyeret Edin Tüm Mesajlarını Bul
Alıntı Yaparak Cevapla
« Önceki | Sonraki »
Cevapla 


'Microsoft Terrarium' Konusunu Paylaş
  • RSS
  • del.icio.us
  • StumbleUpon
  • Digg
  • TwitThis
  • Facebook
  • Reddit
  • Google
  • YahooMyWeb
  • E-mail

Forum Atla:


İletişim | SistemOdasi.net | Yukarıya dön | İçeriğe Dön | RSS
site ekle
Zirve100
Toplist