Why are my curved edges not updating correctly? - layout

I'm trying to customize a layout of JGraph. I want to create curved edges, but I have a problem. Every time I create a group of vertex on JGraph, and I am firing an event to update this graph, the edge is missing points compared to the previous state. Here is a example:
Can someone help me?
Here is my code:
class CurveGraphView extends mxGraphView {
public CurveGraphView(mxGraph graph) {
super(graph);
}
/* Only override this if you want the label to automatically position itself on the control point */
#Override
public mxPoint getPoint(mxCellState state, mxGeometry geometry) {
double x = state.getCenterX();
double y = state.getCenterY();
if (state.getAbsolutePointCount() == 3) {
mxPoint mid = state.getAbsolutePoint(1);
x = mid.getX();
y = mid.getY();
}
return new mxPoint(x, y);
}
// /* Makes sure that the full path of the curve is included in the bounding box */
#Override
public mxRectangle updateBoundingBox(mxCellState state) {
List<mxPoint> points = state.getAbsolutePoints();
mxRectangle bounds = super.updateBoundingBox(state);
Object style = state.getStyle().get("edgeStyle");
if (CurvedEdgeStyle.KEY.equals(style) && points != null && points.size() == 3) {
Rectangle pathBounds = CurvedShape.createPath(state.getAbsolutePoints()).getBounds();
Rectangle union = bounds.getRectangle().union(pathBounds);
bounds = new mxRectangle(union);
state.setBoundingBox(bounds);
}
return bounds;
}
}
class CurvedEdgeStyle implements mxEdgeStyle.mxEdgeStyleFunction {
public static final String KEY = "curvedEdgeStyle";
#Override
public void apply(mxCellState state, mxCellState source, mxCellState target, List<mxPoint> points, List<mxPoint> result) {
mxPoint pt = (points != null && points.size() > 0) ? points.get(0) : null;
if (source != null && target != null) {
double x = 0;
double y = 0;
if (pt != null) {
result.add(pt);
} else {
x = (target.getCenterX() + source.getCenterX()) / 2;
y = (target.getCenterY() + source.getCenterY()) / 2;
mxPoint point = new mxPoint(x, y);
result.add(point);
}
}
}
}
class CurvedShape extends mxConnectorShape {
public static final String KEY = "curvedEdge";
private GeneralPath path;
#Override
public void paintShape(mxGraphics2DCanvas canvas, mxCellState state) {
List<mxPoint> abs = state.getAbsolutePoints();
int n = state.getAbsolutePointCount();
mxCell aux = (mxCell)state.getCell();
if (n < 3) {
super.paintShape(canvas, state);
} else if (configureGraphics(canvas, state, false)) {
Graphics2D g = canvas.getGraphics();
path = createPath(abs);
g.draw(path);
paintMarker(canvas, state, false);
paintMarker(canvas, state, true);
}
}
/* Code borrowed from here: http://www.codeproject.com/Articles/31859/Draw-a-Smooth-Curve-through-a-Set-of-2D-Points-wit */
public static GeneralPath createPath(List<mxPoint> abs) {
mxPoint[] knots = abs.toArray(new mxPoint[abs.size()]);
int n = knots.length - 1;
mxPoint[] firstControlPoints = new mxPoint[n];
mxPoint[] secondControlPoints = new mxPoint[n]; // Calculate first Bezier control points // Right hand side vector
double[] rhs = new double[n]; // Set right hand side X values
for (int i = 1; i < n - 1; ++i) {
rhs[i] = 4 * knots[i].getX() + 2 * knots[i + 1].getX();
}
rhs[0] = knots[0].getX() + 2 * knots[1].getX();
rhs[n - 1] = (8 * knots[n - 1].getX() + knots[n].getX()) / 2.0; // Get first control points X-values
double[] x = getFirstControlPoints(rhs); // Set right hand side Y values
for (int i = 1; i < n - 1; ++i) {
rhs[i] = 4 * knots[i].getY() + 2 * knots[i + 1].getY();
}
rhs[0] = knots[0].getY() + 2 * knots[1].getY();
rhs[n - 1] = (8 * knots[n - 1].getY() + knots[n].getY()) / 2.0; // Get first control points Y-values
double[] y = getFirstControlPoints(rhs); // Fill output arrays.
for (int i = 0; i < n; ++i) { // First control point
firstControlPoints[i] = new mxPoint(x[i], y[i]); // Second control point
if (i < n - 1) {
secondControlPoints[i] = new mxPoint(2 * knots[i + 1].getX() - x[i + 1], 2 * knots[i + 1].getY() - y[i + 1]);
} else {
secondControlPoints[i] = new mxPoint((knots[n].getX() + x[n - 1]) / 2, (knots[n].getY() + y[n - 1]) / 2);
}
}
GeneralPath path = new GeneralPath();
path.moveTo(knots[0].getX(), knots[0].getY());
for (int i = 1; i < n + 1; i++) {
path.curveTo(firstControlPoints[i - 1].getX(), firstControlPoints[i - 1].getY(), secondControlPoints[i - 1].getX(), secondControlPoints[i - 1].getY(), knots[i].getX(), knots[i].getY());
}
return path;
}/// <summary>/// Solves a tridiagonal system for one of coordinates (x or y)/// of first Bezier control points./// </summary>/// <param name="rhs">Right hand side vector.</param>/// <returns>Solution vector.</returns>
private static double[] getFirstControlPoints(double[] rhs) {
int n = rhs.length;
double[] x = new double[n]; // Solution vector.
double[] tmp = new double[n]; // Temp workspace.
double b = 2.0;
x[0] = rhs[0] / b;
for (int i = 1; i < n; i++) // Decomposition and forward substitution.
{
tmp[i] = 1 / b;
b = (i < n - 1 ? 4.0 : 3.5) - tmp[i];
x[i] = (rhs[i] - x[i - 1]) / b;
}
for (int i = 1; i < n; i++) {
x[n - i - 1] -= tmp[n - i] * x[n - i]; // Backsubstitution.
}
return x;
}
#Override
protected mxLine getMarkerVector(List<mxPoint> points, boolean source, double markerSize) {
if (path == null || points.size() < 3) {
return super.getMarkerVector(points, source, markerSize);
}
double coords[] = new double[6];
double x0 = 0;
double y0 = 0;
double x1 = 0;
double y1 = 0;
PathIterator p = path.getPathIterator(null, 2.0);
if (source) {
p.currentSegment(coords);
x1 = coords[0];
y1 = coords[1];
p.next();
p.currentSegment(coords);
x0 = coords[0];
y0 = coords[1];
} else {
while (!p.isDone()) {
p.currentSegment(coords);
x0 = x1;
y0 = y1;
x1 = coords[0];
y1 = coords[1];
p.next();
}
}
return new mxLine(x0, y0, new mxPoint(x1, y1));
}
}
extends mxGraph and Override the constructor adding:
mxGraphics2DCanvas.putShape(CurvedShape.KEY, new CurvedShape());
mxStyleRegistry.putValue(CurvedEdgeStyle.KEY, new CurvedEdgeStyle());
getStylesheet().getDefaultEdgeStyle().put(mxConstants.STYLE_SHAPE, CurvedShape.KEY);
getStylesheet().getDefaultEdgeStyle().put(mxConstants.STYLE_EDGE, CurvedEdgeStyle.KEY);
and Override createGraphView() returning CurveGraphView.
Have told me it has to do something with absolute points.

Related

Threaded Terrain Generation 3d Bug Unity

So I have this weird bug in my terrain generation project
I have 2 methods that were supposed to fix offsets for different noise scales between chunks but for some reason when I implimented threading it stopped working in seemingly random areas. I'm 100% sure this worked before threading.
public struct GetMeshData : IJob
{
public ChunkData chunkData;
public NativeArray<float> noiseMap;
public MeshData meshData;
public void Execute()
{
for (int z = 0; z < chunkData.chunkSize + 1; z++)
{
for (int x = 0; x < chunkData.chunkSize + 1; x++)
{
noiseMap[z * (chunkData.chunkSize + 1) + x] = Noise.GetNoiseValue(chunkData, x, z);
}
}
MeshData temporaryMeshData = MeshGeneration.GenerateMesh(chunkData, noiseMap, meshData.triangles, meshData.vertices, meshData.uvs);
meshData = temporaryMeshData;
}
public GetMeshData(ChunkData chunkData, NativeArray<Vector3> vertices, NativeArray<Vector2> uvs, NativeArray<int> triangles, NativeArray<float> noiseMap)
{
this.chunkData = chunkData;
this.meshData = new MeshData(vertices, uvs, triangles);
this.noiseMap = noiseMap;
}
}
this is the job while this is my code to handle it
for (int i = 0; i < meshJob.Count; i++)
{
if (meshJob[i].IsCompleted)
{
meshJob[i].Complete();
TerrainChunk currentChunk = chunks[meshJobData[i].chunkData.chunkPosition.x,
meshJobData[i].chunkData.chunkPosition.y];
PostMeshGeneration(currentChunk, meshJobData[i].meshData);
toBeAdjusted.Add(currentChunk);
meshJobData[i].noiseMap.Dispose();
meshJobData[i].meshData.vertices.Dispose();
meshJobData[i].meshData.triangles.Dispose();
meshJobData[i].meshData.uvs.Dispose();
meshJob.RemoveAt(i);
meshJobData.RemoveAt(i);
}
}
this is what I do after the job is complete:
public void PostMeshGeneration(TerrainChunk chunk, MeshData meshData)
{
Mesh mesh = new Mesh();
mesh.vertices = meshData.vertices.ToArray();
mesh.triangles = meshData.triangles.ToArray();
mesh.uv = meshData.uvs.ToArray();
chunk.GetChunkGameObject().GetComponent<MeshFilter>().mesh = mesh;
ReadjustMeshCollider(chunk);
}
lastly this is trying to fix the scale offsets
if (toBeAdjusted.Count != 0 && meshJob.Count == 0 && meshJobData.Count == 0)
{
while (toBeAdjusted.Count > 0)
{
TerrainChunk currentChunk = toBeAdjusted[0];
Mesh mesh = currentChunk.GetChunkGameObject().GetComponent<MeshFilter>().mesh;
AdjustNoiseScaling(currentChunk);
FixCornerVerticesOffset(currentChunk);
mesh.UploadMeshData(false);
ApplyColorsToChunk(currentChunk, mesh.vertices);
ReadjustMeshCollider(currentChunk);
toBeAdjusted.RemoveAt(0);
}
}
if you need to see more code go to the github link https://github.com/htmhell69/TerrainGenerationUnity

Unity - Infinite terrain gaps betwean chunks?

So I am creating an endless terrain.
I can create the terrain but my chunks have gaps betwean them and they don't align properly.
I think the problem might be caused by my Noise Generation script, but I am not sure.
This is my Noise Generation script
public static class Noise_GENERATOR
{
public static float[,] GenerateNoise(int chunkSize, int octaves, int seed, float noiseScale, float persistence, float lacunarity, Vector2 offset)
{
float[,] noiseMap = new float[chunkSize, chunkSize];
System.Random prng = new System.Random(seed);
Vector2[] octaveOffsets = new Vector2[octaves];
float maxPossibleHeight = 0;
float amplitude = 1;
float frequency = 1;
for (int i = 0; i < octaves; i++)
{
float offsetX = prng.Next(-100000, 100000) + offset.x;
float offsetY = prng.Next(-100000, 100000) + offset.y;
octaveOffsets[i] = new Vector2(offsetX, offsetY);
maxPossibleHeight += amplitude;
amplitude *= persistence;
}
if (noiseScale <= 0)
{
noiseScale = 0.0001f;
}
float maxLocalNoiseHeight = float.MinValue;
float minLocalNoiseHeight = float.MaxValue;
float halfWidth = chunkSize / 2f;
float halfHeight = chunkSize / 2f;
for (int y = 0; y < chunkSize; y++)
{
for (int x = 0; x < chunkSize; x++)
{
amplitude = 1;
frequency = 1;
float noiseHeight = 0;
for (int i = 0; i < octaves; i++)
{
float sampleX = (x-halfWidth + octaveOffsets[i].x) / noiseScale * frequency;
float sampleY = (y-halfHeight + octaveOffsets[i].y) / noiseScale * frequency;
float perlinValue = Mathf.PerlinNoise(sampleX, sampleY) * 2 - 1;
noiseHeight += perlinValue * amplitude;
amplitude *= persistence;
frequency *= lacunarity;
}
if (noiseHeight > maxLocalNoiseHeight)
{
maxLocalNoiseHeight = noiseHeight;
}
else if (noiseHeight < minLocalNoiseHeight)
{
minLocalNoiseHeight = noiseHeight;
}
noiseMap[x, y] = noiseHeight;
float normalizedHeight = (noiseMap[x, y] + 1) / (maxPossibleHeight / 0.9f);
noiseMap[x, y] = Mathf.Clamp(normalizedHeight, 0, int.MaxValue);
}
}
return noiseMap;
}
}
To Generate the height of a mesh, I am using Animation Curve and multiplying it by elevationScale variable.
float height = heightCurve.Evaluate(noiseMap[x, y]) * elevationScale;
I thought about accesing each Terrain chunk and getting the height of the edges and matching them together but that would look really weird and I don't know how to do it properly.
EDIT: Here just in case my Mesh generator script and how I am creating the Terrain chunk
public static class Mesh_GENERATOR
{
public static MeshData GenerateChunkMesh(int chunkSize,float[,] noiseMapData,float elevationScale,AnimationCurve terrainCurve,int LODlevel )
{
float[,] noiseMap = noiseMapData;
AnimationCurve heightCurve = new AnimationCurve(terrainCurve.keys);
//Setup variables
Vector3[] vertices = new Vector3[chunkSize * chunkSize];
int[] triangles = new int[(chunkSize - 1) * (chunkSize - 1) * 6];
Vector2[] uvs = new Vector2[chunkSize * chunkSize];
int triangle = 0;
int levelOfDetailIncrement = (LODlevel == 0) ? 1 : LODlevel * 2;
int numberOfVerticesPerRow = (chunkSize) / levelOfDetailIncrement + 1;
for (int y = 0; y < chunkSize; y++)
{
for (int x = 0; x < chunkSize; x++)
{
int i = y * chunkSize + x;
//Create vertices at position and center mesh
float height = heightCurve.Evaluate(noiseMap[x, y]) * elevationScale;
Vector2 percentPosition = new Vector2(x / (chunkSize - 1f), y / (chunkSize -1f ));
Vector3 vertPosition = new Vector3(percentPosition.x * 2 - 1, 0, percentPosition.y * 2 - 1) * chunkSize/2;
vertPosition.y = height;
vertices[i] = vertPosition;
uvs[i] = new Vector2((float)x / chunkSize, (float)y / chunkSize);
//Construct triangles
if (x != chunkSize - 1 && y != chunkSize - 1)
{
triangles[triangle + 0] = i + chunkSize;
triangles[triangle + 1] = i + chunkSize + 1;
triangles[triangle + 2] = i;
triangles[triangle + 3] = i + chunkSize + 1;
triangles[triangle + 4] = i + 1;
triangles[triangle + 5] = i;
triangle += 6;
}
}
}
MeshData meshData = new MeshData(chunkSize, vertices, triangles, uvs);
return meshData;
}
}
public class MeshData
{
public int chunkSize;
public Vector3[] vertices;
public int[] triangles;
public Vector2[] uvs;
public Mesh mesh;
public MeshData(int chunkSize,Vector3[] vertices,int[] triangles, Vector2[] uvs)
{
this.chunkSize = chunkSize;
this.vertices = vertices;
this.triangles = triangles;
this.uvs = uvs;
}
public Mesh CreateMesh()
{
if(mesh == null) { mesh = new Mesh(); } else { mesh.Clear(); }
mesh.indexFormat = UnityEngine.Rendering.IndexFormat.UInt32;
mesh.vertices = vertices;
mesh.triangles = triangles;
mesh.uv = uvs;
mesh.RecalculateNormals();
return mesh;
}
}
And here is my TerrainChunk
public class TerrainChunk
{
GameObject meshObject;
Vector2 position;
Bounds bounds;
MeshRenderer meshRenderer;
MeshFilter meshFilter;
public TerrainChunk(Vector2 coord, int chunkSize, Transform parent,Material terrainMaterial)
{
position = coord * chunkSize;
bounds = new Bounds(position, Vector2.one * chunkSize);
Vector3 positionV3 = new Vector3(position.x , 0, position.y );
Debug.Log("CHUNK: COORD" + coord + "POSITION" + position + "POSITION3V" + positionV3);
meshObject = new GameObject("Terrain Chunk");
meshFilter = meshObject.AddComponent<MeshFilter>();
meshRenderer = meshObject.AddComponent<MeshRenderer>();
meshRenderer.material = terrainMaterial;
meshObject.transform.position = positionV3;
meshObject.transform.parent = parent;
SetVisible(false);
worldGenerator.RequestMapData(position,OnNoiseDataReceived);
}
void OnNoiseDataReceived(MapData mapData)
{
worldGenerator.RequestMeshData(mapData, OnMeshDataReceived);
}
void OnMeshDataReceived(MeshData meshData)
{
meshFilter.mesh = meshData.CreateMesh();
}
public void UpdateTerrainChunk(Vector2 viewerPosition, int maxRenderDistance)
{
float viewerDstFromNearestEdge = Mathf.Sqrt(bounds.SqrDistance(viewerPosition));
bool visible = viewerDstFromNearestEdge <= maxRenderDistance;
SetVisible(visible);
}
public void SetVisible(bool visible)
{
meshObject.SetActive(visible);
}
public bool IsVisible()
{
return meshObject.activeSelf;
}
}
}
If I undestand all your values and variables correctly.
The problem might lay in the Noise Generator.
You need to create the chunkSize to be bigger by 1 so if you are passing 250 you will need to pass 251, as the for loop in the Noise Generator stops at 249 and not 250. (I might be wrong about this ), If you do this the mesh generator will now have the right values for calculation.
So your chunksize variable should look like this
chunkSize = chunkSize + 1;
Now there will still be smaller gaps and the mesh will clip through each other, so to fix this you will need to position the Chunk and you do it this way ->
(If your coord serves as a direction in which the chunk will be created from your World generator object -> for example chunks pointing North will be with values x:0 y:1, chunks pointing West will be x:-1 y:0, NorthWest chunks x:-1 y:-1 and so on), you may need to change the 0.5f to your values so the chunks align properly.
Vector3 positionV3 = new Vector3(position.x + (coord.x + 0.5f), 0, position.y + (coord.y + 0.5f) );
There still may be some smaller gaps visible in the terrain, but this can be fixed by playing with the values, or you can try and access each Chunk and get the edge vertices and their heights and connect the chunks together this way.

Processing, simple "raytracing" engine "target VM failed to initialize"

I've been trying to fix this thing for a while now but it doesn't seem to work; "Could not run the sketch (Target VM failed to initialize)."
I'll post the full code down below.
In the draw(), there are three for loops.
for(int i = 0; i<objectAmount; i++) {
circles[i].drawObj();
}
The first one creates the circles, while the second nested ones take care of collision and drawing the lines;
for(int i = 0; i<rayAmount; i++) {
rays[i].update();
for(int j = 0; j<objectAmount; j++) {
rays[i].collide(circles[j]);
}
line(rays[i].xPos, rays[i].yPos, rays[i].xEnd, rays[i].yEnd);
}
the .collide takes point on the 'ray' and moves closer to the circle until it reaches some value, where it marks the line's end, which is then used by the line() function to draw it to the circle.
For some reason, when I implemented the .collide function, everything stopped working unless I set the amount of rays to one, in which case no rays would appear but the circle generation would follow along just fine.
int rayAmount = 45;
int angleCorrect = 360/rayAmount;
int objectAmount = 10;
Ray[] rays = new Ray[rayAmount];
Object[] circles = new Object[objectAmount];
void setup() {
size(600, 400, P2D);
for(int i = 0; i<rayAmount; i++) {
rays[i] = new Ray(i*angleCorrect);
}
for(int i = 0; i<objectAmount; i++) {
circles[i] = new Object(random(0, 600), random(0, 400), random(20, 100));
}
}
void draw() {
background(255);
stroke(100);
for(int i = 0; i<objectAmount; i++) {
circles[i].drawObj();
}
for(int i = 0; i<rayAmount; i++) {
rays[i].update();
for(int j = 0; j<objectAmount; j++) {
rays[i].collide(circles[j]);
}
line(rays[i].xPos, rays[i].yPos, rays[i].xEnd, rays[i].yEnd);
}
}
class Ray {
float xPos, yPos, Angle, xEnd, yEnd;
Ray(float angle) {
xPos = mouseX;
yPos = mouseY;
Angle = angle;
}
void update() {
xPos = mouseX;
yPos = mouseY;
//xEnd = xPos + 100 * cos(radians(Angle));
//yEnd = yPos + 100 * sin(radians(Angle));
}
void collide(Object other) {
float newXEnd = this.xEnd;
float newYEnd = this.yEnd;
float distToObject = sqrt(pow(other.xPos-this.xPos, 2) + pow(other.yPos-this.yPos, 2));
while(distToObject > 1) {
newXEnd = newXEnd + distToObject * cos(radians(Angle));
newYEnd = newYEnd + distToObject * sin(radians(Angle));
distToObject = sqrt(pow(other.xPos-newXEnd, 2) + pow(other.yPos-newYEnd, 2));
}
this.xEnd = newXEnd;
this.yEnd = newYEnd;
}
}
class Object {
float xPos, yPos, radius;
Object(float x, float y, float r) {
xPos = x;
yPos = y;
radius = r;
}
void drawObj() {
stroke(100);
circle(xPos, yPos, radius);
}
}

What might cause a sprite to stop directional movement when colliding in a 2-D game (the sprite still animates)?

!! This is not my code - I am using this to learn !! However, I do not understand what might cause the sprite to stop it's directional movement when colliding with the "STONE" object. The entire 2-D Game will run and the sprite works properly, but when I move close to the end of the screen or too close to the stone, I get stuck in place. I could not find an explanation I understood completely. I apologize in advance if this is a trivial question to anyone.
Basic Solid Tile Class:
public class BasicSolidTile extends BasicTile {
public BasicSolidTile(int id, int x, int y, int tileColour) {
super(id, x, y, tileColour);
this.solid = true;
}
}
Tile Class:
public abstract class Tile {
public static final Tile[] tiles = new Tile[256];
public static final Tile VOID = new BasicSolidTile(0, 0, 0, Colours.get(000, -1, -1, -1));
public static final Tile STONE = new BasicSolidTile(1, 1, 0, Colours.get(-1, 333, -1, -1));
public static final Tile GRASS = new BasicTile(2, 2, 0, Colours.get(-1, 131, 141, -1));
protected byte id;
protected boolean solid;
protected boolean emitter;
public Tile(int id, boolean isSolid, boolean isEmitter) {
this.id = (byte) id;
if (tiles[id] != null) {
throw new RuntimeException("Duplicate tile id on" + id);
}
this.solid = isSolid;
this.emitter = isEmitter;
tiles[id] = this;
}
public byte getId() {
return id;
}
public boolean isSolid() {
return solid;
}
public boolean isEmitter() {
return emitter;
}
public abstract void render(Screen screen, Level level, int x, int y);
}
Mob Class:
public abstract class Mob extends Entity {
protected String name;
protected int speed;
protected int numSteps = 0;
protected boolean isMoving;
protected int movingDir = 1;
protected int scale = 1;
public Mob(Level level, String name, int x, int y, int speed) {
super(level);
this.name = name;
this.x = x;
this.y = y;
this.speed = speed;
}
public void move(int xa, int ya) {
// you want to check if they are not zero
if (xa != 0 && ya != 0) {
move(xa, 0);
move(0, ya);
numSteps--;
return;
}
numSteps++;
if (!hasCollided(x, y)) {
if (ya < 0)
movingDir = 0;
if (ya > 0)
movingDir = 1;
if (xa < 0)
movingDir = 2;
if (xa > 0)
movingDir = 3;
x += xa * speed;
y += ya * speed;
}
}
public abstract boolean hasCollided(int xa, int ya);
protected boolean isSolidTile(int xa, int ya, int x, int y) {
if (level == null) {
return false;
}
Tile lastTile = level.getTile((this.x + x) >> 3, (this.y + y) >> 3);
Tile newTile = level.getTile((this.x + x + xa) >> 3, (this.y + y + ya) >> 3);
if (!lastTile.equals(newTile) && newTile.isSolid()) {
return true;
}
return false;
}
public String getName() {
return name;
}
}
Level Class:
public class Level {
// array of id's
private byte[] tiles;
public int width;
public int height;
public List<Entity> entities = new ArrayList<Entity>();
public Level(int width, int height) {
tiles = new byte[width * height];
this.width = width;
this.height = height;
this.generateLevel();
}
public void generateLevel() {
for (int y = 0; y < height; y++) {
for (int x = 0; x < width; x++) {
if (x * y %10 < 7) {
tiles[x + y * width] = Tile.GRASS.getId();
} else {
tiles[x + y * width] = Tile.STONE.getId();
}
}
}
}
public void tick() {
// loop through all the vars if you dont need an index var
for (Entity e : entities) {
e.tick();
}
}
public void renderTiles(Screen screen, int xOffset, int yOffset) {
if (xOffset < 0)
xOffset = 0;
if (xOffset > ((width << 3) - screen.width))
xOffset = ((width << 3) - screen.width);
if (yOffset < 0)
yOffset = 0;
if (yOffset > ((height << 3) - screen.height))
yOffset = ((height << 3) - screen.height);
screen.setOffset(xOffset, yOffset);
for (int y = (yOffset >> 3); y < (yOffset + screen.height >> 3) + 1; y++) {
for (int x = (xOffset >> 3); x < (xOffset + screen.width >> 3) + 1; x++) {
getTile(x, y).render(screen, this, x << 3, y << 3);
}
}
}
public void renderEntities(Screen screen) {
for (Entity e : entities) {
e.render(screen);
}
}
public Tile getTile(int x, int y) {
if (0 > x || x >= width || 0 > y || y >= height)
return Tile.VOID;
return Tile.tiles[tiles[x + y * width]];
}
public void addEntity(Entity entity) {
this.entities.add(entity);
}
}
Player Class:
public class Player extends Mob {
private InputHandler input;
private int colour = Colours.get(-1, 111, 145, 543);
private int scale = 1;
public Player(Level level, int x, int y, InputHandler input) {
super(level, "Player", x, y, 1);
this.input = input;
}
public void tick() {
int xa = 0;
int ya = 0;
if (input.up.isPressed()) {
ya--;
}
if (input.down.isPressed()) {
ya++;
}
if (input.left.isPressed()) {
xa--;
}
if (input.right.isPressed()) {
xa++;
}
if (xa != 0 || ya != 0) {
move(xa, ya);
isMoving = true;
} else {
isMoving = false;
}
this.scale = 1;
}
public void render(Screen screen) {
int xTile = 0;
int yTile = 28;
int walkingSpeed = 4;
int flipTop = (numSteps >> walkingSpeed) & 1;
int flipBottom = (numSteps >> walkingSpeed) & 1;
if (movingDir == 1) {
xTile += 2;
} else if (movingDir > 1) {
xTile += 4 + ((numSteps >> walkingSpeed) & 1) * 2;
flipTop = (movingDir - 1) % 2;
}
int modifier = 8 * scale;
int xOffset = x - modifier / 2;
int yOffset = y - modifier / 2 - 4;
// upper body
screen.render(xOffset + (modifier * flipTop), yOffset, xTile + yTile * 32, colour, flipTop, scale);
screen.render(xOffset + modifier - (modifier * flipTop), yOffset, (xTile + 1) + yTile * 32, colour, flipTop, scale);
// lower body
screen.render(xOffset + (modifier * flipBottom), yOffset + modifier, xTile + (yTile + 1) * 32, colour, flipBottom, scale);
screen.render(xOffset + modifier - (modifier * flipBottom), yOffset + modifier, (xTile + 1) + (yTile + 1) * 32, colour, flipBottom,
scale);
}
public boolean hasCollided(int xa, int ya) {
int xMin = 0;
int xMax = 7;
int yMin = 3;
int yMax = 7;
for (int x = xMin; x < xMax; x++) {
if (isSolidTile(xa, ya, x, yMin)) {
return true;
}
}
for (int x = xMin; x < xMax; x++) {
if (isSolidTile(xa, ya, x, yMax)) {
return true;
}
}
for (int y = yMin; y < yMax; y++) {
if (isSolidTile(xa, ya, xMin, y)) {
return true;
}
}
for (int y = yMin; y < yMax; y++) {
if (isSolidTile(xa, ya, xMax, y)) {
return true;
}
}
return false;
}
}
Okay. It took me FOREVER, but it was a simple fix. All I had to do was change the "(x, y)" to "(xa, ya)"
if (!hasCollided(xa, ya)) {
if (ya < 0)
movingDir = 0;
if (ya > 0)
movingDir = 1;
if (xa < 0)
movingDir = 2;
if (xa > 0)
movingDir = 3;
x += xa * speed;
y += ya * speed;
}
}

j2me program to create a GRID menu?

I want to create a list of operation's in a grid view. For example visit this URL.
http://cdn-static.cnet.co.uk/i/product_media/40000186/nokia1616_01.jpg
You can look at this question or this page(and use LWUIT or CustomItems) or extend "canvas".In this way you need to two pictures for every operation in grid view.One for normal state and another for highlighted.Here is a simple canvas that represents 4 operations in 2*2 grid:
public class GridCanvas extends Canvas {
int highlightedRow = 0;
int highlightedColumn = 0;
Image[][] normalImageMat;
Image[][] highlightedImageMat;
Image[][] imageMat;
int gridColumnNo;
int gridRowNo;
/**
* constructor
*/
public GridCanvas() {
gridColumnNo = 2;
gridRowNo = 2;
normalImageMat = new Image[gridRowNo][gridColumnNo];
highlightedImageMat = new Image[gridRowNo][gridColumnNo];
imageMat = new Image[gridRowNo][gridColumnNo];
try {
for (int i = 0; i < gridRowNo; i++) {
for (int j = 0; j < gridColumnNo; j++) {
normalImageMat[i][j] = Image.createImage("/hello/normalImage" + i + j + ".png");
}
}
for (int i = 0; i < gridRowNo; i++) {
for (int j = 0; j < gridColumnNo; j++) {
highlightedImageMat[i][j] = Image.createImage("/hello/highlightedImage" + i + j + ".png");
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
/**
* paint
*/
public void paint(Graphics g) {
g.setColor(255, 255, 255);
g.fillRect(0, 0, getWidth(), getHeight());
for (int i = 0; i < gridRowNo; i++) {
System.arraycopy(normalImageMat[i], 0, imageMat[i], 0, 2);
}
imageMat[highlightedRow][highlightedColumn] = highlightedImageMat[highlightedRow][highlightedColumn];
int width = 0;
int height = 0;
for (int i = 0; i < gridRowNo; i++) {
for (int j = 0; j < gridColumnNo; j++) {
g.drawImage(imageMat[i][j], width, height, 0);
width = width + imageMat[i][j].getWidth();
}
width = 0;
height = height + imageMat[0][0].getHeight();
}
}
/**
* Called when a key is pressed.
*/
protected void keyPressed(int keyCode) {
int gameAction = this.getGameAction(keyCode);
if (gameAction == RIGHT) {
highlightedColumn = Math.min(highlightedColumn + 1, gridColumnNo - 1);
} else if (gameAction == LEFT) {
highlightedColumn = Math.max(highlightedColumn - 1, 0);
} else if (gameAction == UP) {
highlightedRow = Math.max(0, highlightedRow - 1);
} else if (gameAction == DOWN) {
highlightedRow = Math.min(gridRowNo - 1, highlightedRow + 1);
}
repaint();
}
}
In real samples you would to detect gridColumnNo and gridRowNo due to screen and your icons dimensions.
If you can not go with LWUIT (license, library size, etc) and do not want to leave the screen rendering to LCDUI (CustomItem), you should extend Canvas.
I have shared code for an adaptive grid at http://smallandadaptive.blogspot.com.br/2010/12/touch-menu.html Feel free to use it.
At this sample all items are Strings, but you can change the TouchItem to draw Images instead.

Resources