一、题目要求
最近在听funk音乐,感觉真个人都舒服了,些这个作业的时候身体一直在抖,这次要完成的作业是参考《代码本色》教程,运用不少于3个章节的动画技术,实现一个交互应用,将动画技术充分运用于交互过程中;
做了一个小游戏,
整个游戏的玩法就是通过鼠标控制粉色小球移动,小的方块是食物,可以被吃掉,其他的的大球是怪物了,如果他们碰到你就会减分数并且会卡顿,分数显示在左上角
背景是声音的波动,加载了一首bgm,会根据节奏抖动,其实可以使怪物的移动也和音乐结合起来,但是奈何太懒了,暂时就这样了。
其实代码并没有多复杂了,比较复杂的地方是怪物的成长是根据基因模拟的,每个怪物一开始都会随机初始的基因,根据基因来绘制大小,有一定几率分裂和随机产生,然后个体生命会随着时间衰减,当他们碰到玩家控制的小球后就会重新变得满生命值
二、实践内容
通过processing对图像进行处理
homework——主要运行脚本,主要运行world和bgm的可视化
bloop——模拟怪物的存在,并且写移动,复制,变异和更新的函数,写吃食物和玩家后变大和长生命的函数
DNA——主要写怪物的基因函数,其实这整个就是一个遗传变异的模拟了,以01序列来模拟基因
player——写玩家控制的函数
WORLD——写玩家食物和怪物生成的函数
三、源代码
homework——主要运行脚本,主要运行world和bgm的可视化
import processing.sound.*;
// Declare the sound source and Waveform analyzer variables
SoundFile sample;
Waveform waveform;
// Define how many samples of the Waveform you want to be able to read at once
int samples = 100;
World world;
void setup() {
size(640, 360);
// Load and play a soundfile and loop it.
sample = new SoundFile(this, "beat.aiff");
sample.loop();
// Create the Waveform analyzer and connect the playing soundfile to it.
waveform = new Waveform(this, samples);
waveform.input(sample);
// World starts with 20 creatures
// and 20 pieces of food
world = new World(20);
smooth();
}
void draw() {
background(30, 30, 240);
// Set background color, noFill and stroke style
stroke(255);
strokeWeight(2);
noFill();
// Perform the analysis
waveform.analyze();
beginShape();
for(int i = 0; i < samples; i++){
// Draw current data of the waveform
// Each sample in the data array is between -1 and +1
vertex(
map(i, 0, samples, 0, width),
map(waveform.data[i], -1, 1, 0, height)
);
}
endShape();
String time = "Sorce is " + millis()/100;
pushMatrix();
translate(0, 0, 0);
textSize(32);
stroke(255, 255, 0);
text(time, 40, 80);
noStroke();
popMatrix();
world.run();
}
bloop——模拟怪物的存在,并且写移动,复制,变异和更新的函数,写吃食物和玩家后变大和长生命的函数
class Bloop {
PVector position; // position
DNA dna; // DNA
float health; // Life timer
float xoff; // For perlin noise
float yoff;
// DNA will determine size and maxspeed
float r;
float maxspeed;
// Create a "bloop" creature
Bloop(PVector l, DNA dna_) {
position = l.get();
health = 200;
xoff = random(1000);
yoff = random(1000);
dna = dna_;
// Gene 0 determines maxspeed and r
// The bigger the bloop, the slower it is
maxspeed = map(dna.genes[0], 0, 1, 15, 5);//对速度的映射
r = map(dna.genes[0], 0, 1, 20, 50);//半径映射,都跟基因序列有关
}
void run() {
update();
borders();
display();
}
// A bloop can find food and eat it
void eat(Food f, Player player) {
ArrayList<PVector> food = f.getFood();
// Are we touching any food objects?
for (int i = food.size()-1; i >= 0; i--) {
PVector foodposition = food.get(i);
float d = PVector.dist(position, foodposition);
// If we are, juice up our strength!
if (d < r/2) {
health += 100;
food.remove(i);
}
}
PVector playerposition=player.get();
float d = PVector.dist(position, playerposition);
// If we are, juice up our strength!
if (d < (r+player.getr())/2) {
if (player.getr()<r) {
health += 100;
println("die");
delay(100);
} else {
player.health+=100;
health=0;
}
}
}
// At any moment there is a teeny, tiny chance a bloop will reproduce
Bloop reproduce() {
// asexual reproduction
if (random(1) < 0.0005) {
// Child is exact copy of single parent
DNA childDNA = dna.copy();
// Child DNA can mutate
childDNA.mutate(0.01);
return new Bloop(position, childDNA);
} else {
return null;
}
}
// Method to update position
void update() {
// Simple movement based on perlin noise
float vx = map(noise(xoff), 0, 1, -maxspeed, maxspeed);
float vy = map(noise(yoff), 0, 1, -maxspeed, maxspeed);
PVector velocity = new PVector(vx, vy);
xoff += 0.01;
yoff += 0.01;
position.add(velocity);
// Death always looming
health -= 0.2;
}
// Wraparound
void borders() {
if (position.x < -r) position.x = width+r;
if (position.y < -r) position.y = height+r;
if (position.x > width+r) position.x = -r;
if (position.y > height+r) position.y = -r;
}
// Method to display
void display() {
ellipseMode(CENTER);
stroke(0, health);
fill(0,240,250, health);
ellipse(position.x, position.y, r, r);
}
// Death
boolean dead() {
if (health < 0.0) {
return true;
} else {
return false;
}
}
}
DNA——主要写怪物的基因函数,其实这整个就是一个遗传变异的模拟了,以01序列来模拟基因
class DNA {
// The genetic sequence
float[] genes;
// Constructor (makes a random DNA)
DNA() {
// DNA is random floating point values between 0 and 1 (!!)
genes = new float[1];
for (int i = 0; i < genes.length; i++) {
genes[i] = random(0,1);
}
}
DNA(float[] newgenes) {
genes = newgenes;
}
DNA copy() {
float[] newgenes = new float[genes.length];
//arraycopy(genes,newgenes);
// JS mode not supporting arraycopy
for (int i = 0; i < newgenes.length; i++) {
newgenes[i] = genes[i];
}
return new DNA(newgenes);
}
// Based on a mutation probability, picks a new random character in array spots
void mutate(float m) {
for (int i = 0; i < genes.length; i++) {
if (random(1) < m) {
genes[i] = random(0,1);
}
}
}
}
food——写食物生成和被吃掉的函数
class Food {
ArrayList<PVector> food;
Food(int num) {
// Start with some food
food = new ArrayList();
for (int i = 0; i < num; i++) {
food.add(new PVector(random(width),random(height)));
}
}
// Add some food at a position
void add(PVector l) {
food.add(l.get());
}
// Display the food
void run() {
for (PVector f : food) {
rectMode(CENTER);
stroke(0);
fill(175);
rect(f.x,f.y,8,8);
}
// There's a small chance food will appear randomly
if (random(1) < 0.01) {
food.add(new PVector(random(width),random(height)));
}
}
// Return the list of food
ArrayList getFood() {
return food;
}
}
player——写玩家控制的函数
class Player {
float r=10;
public PVector pos;
float maxspeed=1;
float health=200;
Player(float xpos_, float ypos_) {
pos= new PVector(xpos_, ypos_);
}
void run() {
update();
display();
}
PVector get(){
return pos;
}
float getr(){
return r+health/100;
}
void update() {
// Simple movement based on perlin noise
float vx=0,vy=0;
if (keyPressed && (key == CODED)) { // If it’s a coded key
if (keyCode == LEFT) { // If it’s the left arrow
vx=-maxspeed;
} else if (keyCode == RIGHT) { // If it’s the right arrow
vx=maxspeed;
}
if (keyCode == UP) { // If it’s the left arrow
vy=-maxspeed;
} else if (keyCode == DOWN) { // If it’s the right arrow
vy=maxspeed;
}
}
PVector velocity = new PVector(vx, vy);
pos.add(velocity);
pos.x=mouseX;
pos.y=mouseY;
// Death always looming
health -= 0.2;
}
void eat(Food f) {
ArrayList<PVector> food = f.getFood();
// Are we touching any food objects?
for (int i = food.size()-1; i >= 0; i--) {
PVector foodposition = food.get(i);
float d = PVector.dist(pos, foodposition);
// If we are, juice up our strength!
if (d < getr()/2) {
health += 200;
food.remove(i);
}
}
}
void display() {
ellipseMode(CENTER);
stroke(2);
fill(250, 0, 250);
ellipse(mouseX, mouseY, r+health/100, r+health/100);
}
}
WORLD——写玩家食物和怪物生成的函数
// Has bloops and food
class World {
ArrayList<Bloop> bloops; // An arraylist for all the creatures
Food food; //食物
Player player;
// Constructor
World(int num) {
// Start with initial food and creatures
player =new Player(width/2,height/2);
food = new Food(num);
bloops = new ArrayList<Bloop>(); // Initialize the arraylist
for (int i = 0; i < num; i++) {
PVector l = new PVector(random(width),random(height));
DNA dna = new DNA();
bloops.add(new Bloop(l,dna));
}
}
// Make a new creature
void born(float x, float y) {
PVector l = new PVector(x,y);
DNA dna = new DNA();
bloops.add(new Bloop(l,dna));
}
// Run the world
void run() {
// Deal with food
food.run();
player.run();
player.eat(food);
// Cycle through the ArrayList backwards b/c we are deleting
for (int i = bloops.size()-1; i >= 0; i--) {
// All bloops run and eat
Bloop b = bloops.get(i);
b.run();
b.eat(food,player);
// If it's dead, kill it and make food
if (b.dead()) {
bloops.remove(i);
food.add(b.position);
}
// Perhaps this bloop would like to make a baby?
Bloop child = b.reproduce();
if (child != null) bloops.add(child);
}
}
}
我把文件分享在了https://github.com/YonYuan/Homework2这里,需要的请自取!!!