I have a matrix double[][] with arbitrary dimensions but bigger than 300 (maybe in one or maybe on both dimensions). I want to scale it to double[300][300].
My main approach is to interpolate the matrix and bring it up to double[600][600] and then take four elements and find their average, i.e. the elements 0,0, 0,1, 1,0 and 1,1 will be the 0,0 of the final 300x300 matrix.
I have found the interpolation library in JAVA but I cannot figure out how to use it. Can anyone provide some examples or info?
The library is: http://docs.oracle.com/cd/E17802_01/products/products/java-media/jai/forDevelopers/jai-apidocs/javax/media/jai/Interpolation.html
Thnx.
What about writing a simple method that maps source cells to destination, then averages out?
public static boolean matrixReduce(double[][] dst, double[][] src) {
double dstMaxX = dst.length - 1, dstMaxY = dst[0].length - 1;
double srcMaxX = src.length - 1, srcMaxY = src[0].length - 1;
int count[][] = new int[dst.length][dst[0].length];
for (int x = 0; x < src.length; x++) {
for (int y = 0; y < src[0].length; y++) {
int xx = (int) Math.round((double) x * dstMaxX / srcMaxX);
int yy = (int) Math.round((double) y * dstMaxY / srcMaxY);
dst[xx][yy] += src[x][y];
count[xx][yy]++;
}
}
for (int x = 0; x < dst.length; x++) {
for (int y = 0; y < dst[0].length; y++) {
dst[x][y] /= count[x][y];
}
}
return true;
}
Related
I am trying to make Space Invaders in Processing. I am currently working on getting the enemy to move correctly. I have got them to be drawn in the right spot but I haven't gotten them to be moved correctly. Here is my code:
PImage mainPlayer;
PImage enemyPlayer;
float Xspeed = 60;
float Yspeed = 60;
float X;
float Y;
Enemy EnemyPlayer = new Enemy("EnemyPlayerSpaceInvaders.png", 10, 10, 6);
void setup() {
size(1400, 800);
//enemyPlayer = loadImage("EnemyPlayerSpaceInvaders.png");
mainPlayer = loadImage("MainPlayerSpaceInvaders.png");
}
void draw() {
background(0);
Enemy[] enemyPlayer = new Enemy[60];
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
enemyPlayer[j *i] = new Enemy("EnemyPlayerSpaceInvaders.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
if(enemyPlayer[j * i].alive){
enemyPlayer[j * i].Draw();
}
enemyPlayer[j *i].moveAndDraw(6);
}
}
}
class Enemy {
boolean alive = true;
float x;
float y;
float speed;
String playerTexFile;
PImage playerTex;
Enemy(String PlayerTexFile, float X, float Y, float Speed){
x = X;
y = Y;
speed = Speed;
playerTexFile = PlayerTexFile;
}
void Draw(){
playerTex = loadImage(playerTexFile);
image(playerTex, x, y);
}
void moveAndDraw(float Speed){
playerTex = loadImage(playerTexFile);
if(alive){
x += Speed;
if (x >= 1300) {
x = 100;
y += 50;
}
}
}
}
Here is my result:
The Draw function works but what you're seeing that is messing it up is the moveAndDraw() function.
And the enemy drawings aren't moving. I have made this before with c++ SFML but in that there is a very basic getPosition function. The reason I want to get position is that right now I'm having to use inaccurate numbers as the X and Y position and for the enemy to move correctly I need to know exactly what it's position is. I have checked multiple pages on processing.org but none of them helped. I haven't found any getPosition void and all the ones I've seen other people using a void to do this I just haven't been able to get it to work. If there is some code that could get me this to work or just some function I've looked over and even a website page I could look at I'd be open to it. Please tell me anything I can do to get this working.
The issue is that you recreate the enemies in every frame at it's initial position:
void draw() {
background(0);
Enemy[] enemyPlayer = new Enemy[60];
for (int i = 0; i < 5; i += 1) {
for (int j = 0; j < 11; j += 1) {
enemyPlayer[j *i] = new Enemy("EnemyPlayerSpaceInvaders.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
// [...]
}
You've to:
Create a global array of enemies Enemy[] enemyPlayer (and delete PImage enemyPlayer).
Create and initialize the enemies in setup.
Use and move the existing enemies in draw:
Further note, that your loops doesn't do what you expect it to do. Create the enemies in 2 nested loops. If i runs from o to 6 and j from 0 to 10, the the index of an enemy is i*10 + j.
The enemies can be moved in a single loop from 0 to enemyPlayer.length.
//PImage enemyPlayer; <--- DELETE
// global array of enemies
Enemy[] enemyPlayer = new Enemy[60];
// [...]
void setup() {
size(1400, 800);
mainPlayer = loadImage("MainPlayerSpaceInvaders.png");
// create enemies
for (int i = 0; i < 6; i += 1) {
for (int j = 0; j < 10; j += 1) {
enemyPlayer[i*10 + j] = new Enemy("rocket64.png", 50 + j * 100, 5 + 75 * i, 6);
}
}
}
void draw() {
background(0);
// move enemies
for(int i = 0; i < enemyPlayer.length; ++i ) {
if(enemyPlayer[i].alive){
enemyPlayer[i].Draw();
}
enemyPlayer[i].moveAndDraw(6);
}
}
I have been trying to figure out how to create infinite terrain in 3D using perlin noise. I have so far got a terrain that is made of chunks, and when the player moves out of a chunk, new chunks are generated. Chunks out of range are unloaded. So I have the illusion of an infinite world.
I am using perlin noise to create height maps for the chunks (each chunk has its own height map)
My question is how do I seamlessly tile the height map of each chunk so that there aren't horrible gaps in the world between chunks, and without having the same height map for every chunk.
By "gaps in the world" I mean this.
And I followed this to implement perlin noise
Here is my perlin noise code:
private float[][] perlinNoise(int width, int height, int octave, float[][] whiteNoise)
{
float[][] result = new float[width][height];
int samplePeriod = 1 << octave;
float sampleFrequency = 1.0f / samplePeriod;
for (int i = 0; i < width; i++)
{
int x1 = (i / samplePeriod) * samplePeriod;
int x2 = (x1 + samplePeriod) % width;
float xBlend = (i - x1) * sampleFrequency;
for (int j = 0; j < height; j++)
{
int y1 = (j / samplePeriod) * samplePeriod;
int y2 = (y1 + samplePeriod) % height;
float yBlend = (j - y1) * sampleFrequency;
float top = (float) MathHelper.interpolateLinear(whiteNoise[x1][y1], whiteNoise[x2][y1], xBlend);
float bottom = (float) MathHelper.interpolateLinear(whiteNoise[x1][y2], whiteNoise[x2][y2], xBlend);
result[i][j] = (float) MathHelper.interpolateLinear(top, bottom, yBlend);
}
}
return result;
}
public float[][] generatePerlinNoise(int width, int height, Random random, int octaveCount)
{
float[][] whiteNoise = new float[width][height];
float[][][] totalNoise = new float[octaveCount][][];
float[][] perlinNoise = new float[width][height];
float amplitude = 1.0f;
float totalAmplitude = 0.0f;
float persistance = 0.5f;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
whiteNoise[i][j] = random.nextFloat() % 1;
}
}
for (int i = 0; i < octaveCount; i++)
{
totalNoise[i] = perlinNoise(width, height, i, whiteNoise);
}
for (int o = octaveCount - 1; o >= 0; o--)
{
amplitude *= persistance;
totalAmplitude += amplitude;
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
perlinNoise[i][j] += totalNoise[o][i][j] * amplitude;
}
}
}
for (int i = 0; i < width; i++)
{
for (int j = 0; j < height; j++)
{
perlinNoise[i][j] /= totalAmplitude;
}
}
return perlinNoise;
}
Edit: I have just asked about this on GameDev my question there might be more detailed and helpful. Please try and answer there if possible, because I will be looking at this post less and that one more.
Edit: I have realised that my noise code is NOT PERLIN NOISE. It is actually something called VALUE NOISE, which actually doesnt look as good, and wont work for what I need anyway. I cant find any good java implementation of perlin noise. And I dont just want a link to code I can use, I would like to have a tutorial, where I can understand how the algorithm actually works.
This method sets the pixel color from one image to the other. How can i set the pixels from the imgPix array to the screen.pixels array so that the image appears larger on the screen.pixels array? I dumbed down the code to make the concept easy to understand.
public void drawSprite(Screen screen)
{
for(int y = 0; y < 16; y++)
{
for(int x = 0; x < 16; x++)
{
screen.pixels[x + y * screen.WIDTH] = this.imgPix[x + y * this.WIDTH];
}
}
}
A nice little trick that i discover is to cast to an int. this rounds down the number repeating the pattern..
// scale = 2
-------------y = 0,1,2,3,4,5,6,7,8,9 // as y increase.. y++
(int) y/scale = 0,0,1,1,2,2,3,3,4,4
//
// out of 10 numbers 5 were drawn this is scaling up
// As you can see from the above as y increase y/scale repeats with a the correct pattern
// this happends because casting the (int) rounds down.
//
// scale = 0.8
-------------y = 0,1,2,3,4,5,6,7,8,9
(int) y/scale = 0,1,2,3,5,6,7,8,10,11
//
// out of 10 numbers 2 were skipped this is scaling down an image
public void drawSprite(Screen screen,Image image,float scale)
{
for(int y = 0; y < image.height*scale; y++)
{
int scaleY = (int)(y/scale);
for(int x = 0; x < image.width*scale; x++)
{
int scaleX = (int)(x/scale);
screen.pixels[x + y * screen.WIDTH] = image.pixels[scaleX + scaleY * image.width];
}
}
}
I've answered this question before on programmers.stackexchange.com (similar enough to java to be relevant):
https://softwareengineering.stackexchange.com/questions/148123/what-is-the-algorithm-to-copy-a-region-of-one-bitmap-into-a-region-in-another/148153#148153
--
struct {
bitmap bmp;
float x, y, width, height;
} xfer_param;
scaled_xfer(xfer_param src, xfer_param det)
{
float src_dx = dst.width / src.width;
float src_dy = dst.height / src.height;
float src_maxx = src.x + src.width;
float src_maxy = src.y + src.height;
float dst_maxx = dst.x + dst.width;
float dst_maxy = dst.y + dst.height;
float src_cury = src.y;
for (float y = dst.y; y < dst_maxy; y++)
{
float src_curx = src.x;
for (float x = dst.x; x < dst_maxx; x++)
{
// Point sampling - you can also impl as bilinear or other
dst.bmp[x,y] = src.bmp[src_curx, src_cury];
src_curx += src_dx;
}
src_cury += src_dy;
}
}
This is a homework assignment.
Work 19 5/16 is the assignment
http://sites.stuycs.org/home/courses/ml2x/dyrland-weaver/work
I am running this in the program processing, which does not require main methods.
Blob was given to us. We had to make BlobRunner on our own.
Any advice on why my code isn't doing what its supposed to would be appreciated.
FIRST FILE BlobRunner
int popSize = 4;
int wobble = 2;
int numSides = 4;
float rad = 100;
int radInt = (int) rad;
float a = sqrt(popSize);
int rootPop = (int) a;
Blob[][] blobs = new Blob[popSize/rootPop][rootPop];
/*=====================================
The trickiest part of setup is to make
the screen an appropriate size for the
grid of blobs. The grid should be just
big enough to contain all of the blobs.
====================================*/
void setup() {
size ((popSize/rootPop)*(2*(radInt+3)), rootPop*(2*(radInt+3)));
populate();
}
/*=====================================
The main purpose of draw is to go through
the array of blobs and display each.
====================================*/
void draw() {
int createdSoFar = 0;
for (int i = 0; i<rootPop; i++){
for (int j = 0; j<popSize/rootPop; j++){
if (createdSoFar < popSize){
blobs[j][i].display();
}
createdSoFar++;
}
}
}
/*=====================================
Populate the array of blobs.
You can use any values for radius, number of sides
and wobble factor that you'd like, but you must
use x and y coordinates that ensure the blobs
are drawn in a grid without overlaping each other.
Your code should work for any reasonable value
of population (i.e. something that would fit on a
normal monitor).
====================================*/
void populate() {
for (int i = 0; i < rootPop; i++){
float y = 1;
for (int j = 0; j < (popSize/rootPop); j++){
float x = 1;
blobs[j][i] = new Blob (x*(rad+3), y*(rad+3), numSides, radInt, wobble, wobble);
x=x+2;}
y=y+2;}
}
SECOND FILE Blob
/*=====================================
A Blob object is a regular polygon variant that
can have various features.
Instance Variables:
numSides: number of sides
rad: distance from the center of the polygon
to any vertext
x: x coordinate of the center
y: y coordinate of the center
xFactor: "wobble" foctor in the x direction
yFactor: "wobble" factor in the y direction
====================================*/
class Blob {
int numSides;
int rad;
float x;
float y;
int xFactor;
int yFactor;
Blob(float cx, float cy, int sides, int r, int xf, int yf ) {
x = cx;
y = cy;
numSides = sides;
rad = r;
xFactor = xf;
yFactor = yf;
}
void display() {
float nx;
float ny;
int rx, ry;
float sy;
strokeWeight(1);
beginShape();
for( float t = 0; t <= 1; t+=( 1.0/numSides ) ) {
/*
"wobble" effect is created by adding a random number to each
x and y coordinate. The larger the x and y factors, the higher
the possible wobble value could be
*/
rx = (int)random(xFactor);
ry = (int)random(yFactor);
nx = rad * cos( 2 * PI * t ) + x + rx;
ny = rad * sin( 2 * PI * t ) + y + ry;
vertex(nx, ny);
}
endShape();
}
}
Your code runs, thus it is doing what you asked it to do and nothing more.
I asked my cat to check it out though and she was all, "the guy is re-initializing his variables inside each pass of the loop, he'll never get a grid of blobs that way. Tell him to start by moving float y = 1; float x = 1; in populate() outside of the bounds of the two for loops and start debugging from there."
Then she rolled over on to her side and I patted her.
OK. so let's say I have this picture: http://i.stack.imgur.com/oYhJy.png
I'm trying to do a crop (which works -- I just have the wrong numbers) of the image into separate image arrays. The tile image (linked above) is 36 tiles wide and 15 tiles long. So that's 1152 pixels in width (32 tile width * 36 tiles) and 480 pixels in height (32 tile height * 15 tiles).
Here's what I have so far:
for (int xi = 0; xi < 522; xi++) {
int cropHeight = 32;
int cropWidth = 32;
int cropStartX = xi*32;
int cropStartY = 0;
if (xi % 36 == 0) {
cropStartY = xi*32;
}
BufferedImage processedImage = cropMyImage(originalImage, cropWidth, cropHeight, cropStartX, cropStartY);
tiles[xi] = processedImage;
}
What am I doing wrong? It's working technically, but it's getting the wrong tile images.
Probably clearer if you did a double loop rather than trying to use modulus.
int i = 0;
// no need to have these values inside a loop. They are constants.
int cropHeight = 32;
int cropWidth = 32;
for (int x = 0; x < 36; x++) {
for (int y = 0; y < 15; y++) {
int cropStartX = x*32;
int cropStartY = y*32;
BufferedImage processedImage = cropMyImage(originalImage, cropWidth, cropHeight, cropStartX, cropStartY);
tiles[i++] = processedImage;
}
}
Probably should be:
int cropStartX = (xi%36)*32;
int cropStartY = xi/36*32;