How to load an image using LWJGL - java

I've Googled a lot and could not find the answer to this. I know how to load an image, I need to load images that aren't 256 by 256 or a direct power of 2.
Like how could I load an image that's 128 by 384 or something like that.
What I'm using now:
Load an image:
public static Texture cow = loadTexture("res/cow.png");
private static Texture loadTexture(String file){
try {
return TextureLoader.getTexture("JPG", new FileInputStream(new File(file)));
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
Now to draw it on a 3D poly face:
txt.bind();
GL11.glBegin(GL11.GL_QUADS);
{
//GL11.glColor3d(lightLevel, lightLevel, lightLevel);
GL11.glColor3d(l, l, l);
GL11.glTexCoord2f(0,0); GL11.glVertex3f(x1,y1, z1);
GL11.glTexCoord2f(1,0); GL11.glVertex3f(x1+(x2-x1), y1,z1);
GL11.glTexCoord2f(1,1); GL11.glVertex3f(x1+(x2-x1), y1+(y2-y1), z1+(z2-z1));
GL11.glTexCoord2f(0,1); GL11.glVertex3f(x1,y1+(y2-y1), z1+(z2-z1));
}
GL11.glEnd();
Now that works perfectly, I just need to load images that aren't a power of 2.

you could use slick2d, it is way easier to use and works with lwjgl! All you have to do is:
Image title = null;
public static void main(String[] args) {
}
#Override
public void init(GameContainer Gc, StateBasedGame Sbg)
throws SlickException {
/**
* Images
*/
title = new Image("gfx/main_menu/title/new_title.png");
}
#Override
public void render(GameContainer Gc, StateBasedGame Sbg, Graphics G)
throws SlickException {
/**
* Background
*/
G.setColor(Color.white);
G.fillRect(0, 0, w*s, h*s);
/**
* Images
*/
title.draw(titleY*s,titleX*s);
}

Related

Slick2d how to check if a shape contains any object? Java

i'm new to Slick2d and to this page too, i tried asking the slick forums, but there aren't many people so i couldn't get an answer
Anyway, i've been trying to create a platformer engine in Slick2d java game library, and i was thinking of using the contains and intersects methods of the Shape class.
The thing is, if I want to check if a shape contains any object of any kind (or any object from a specific class), Is there a way to do that? all tutorials i've found explain how to test collision with one single shape, but what if i want to check for any object?
package juegoconslick;
import java.util.ArrayList;
import org.newdawn.slick.*;
import org.newdawn.slick.geom.Rectangle;
import org.newdawn.slick.geom.Shape;
public class JuegoConSlick extends BasicGame {
Jugador player;
Input entrada;
Shape hitbox;
bloque bloq;
ArrayList<bloque> bloques = new ArrayList<>();
public JuegoConSlick(){
super("Mi prueba");
}
public static void main(String[] args) {
AppGameContainer juegito;
try{
juegito = new AppGameContainer(new JuegoConSlick());
juegito.setDisplayMode(630,400,false);
juegito.setMaximumLogicUpdateInterval(60);
juegito.setMaximumLogicUpdateInterval(50);
juegito.setAlwaysRender(true);
juegito.setVSync(true);
juegito.start();
}catch(Exception ex){
System.exit(0);
}
}
#Override
public void init(GameContainer gc) throws SlickException {
player = new Jugador();
hitbox = new Rectangle(player.X, player.Y, 10, 10);
bloq = new bloque(50,50,50,50);
}
#Override
public void update(GameContainer gc, int i) throws SlickException {
intersecta();
Input entrad = gc.getInput();
if(entrad.isKeyDown(Input.KEY_RIGHT) && player.X<600){
player.X+=3;
player.sprite.update(1);
hitbox.setX(player.X);
}
if(entrad.isKeyDown(Input.KEY_LEFT) && player.X>0){
player.X-=3;
player.sprite.update(1);
hitbox.setX(player.X);
}
if(entrad.isKeyDown(Input.KEY_UP) && player.Y>0){
player.Y-=3;
player.sprite.update(1);
hitbox.setY(player.Y);
}
if(entrad.isKeyDown(Input.KEY_DOWN) && player.Y<370){
player.Y+=3;
player.sprite.update(1);
hitbox.setY(player.Y);
}
}
#Override
public void render(GameContainer gc, Graphics grphcs) throws SlickException {
grphcs.draw(bloq.bloque);
grphcs.draw(hitbox);
}
public void intersecta(){
try{
if(hitbox.contains(null)){//i tried checking if it didnt contain any object,
}else{
System.exit(0);
}
}catch(Exception ex){
}
}
}
EDIT: i think i have found a solution, though im not sure if its the most efficient.
basiaclly, i'll save all objects of the same class in an ArrayList:
ArrayList<bloque> bloques = new ArrayList<>();
bloques.add(new bloque(50,50,100,100));
bloques.add(new bloque(100,100,100,100));
Then, what im going to do is check the entire arraylist each time i call the intersects method:
public boolean intersecta(){
boolean devuelve=false;
for(int i=0; i<bloques.size(); i++){
if(hitbox.intersects(bloques.get(i).bloque)){
devuelve=true;
}
}
return devuelve;
}
then im going to use the value i get from intersects to decide whether the player can move or not
public void update(GameContainer gc, int i) throws SlickException {
Input entrad = gc.getInput();
if(entrad.isKeyDown(Input.KEY_RIGHT) && player.X<600 && intersecta()==false){
player.X+=3;
player.sprite.update(1);
hitbox.setX(player.X);
}
and so on with the other keys....
so im not sure if its the best solution, but as far as i have seen it seems to be working. I hope this results useful for others.
I recommend to create a new Class.
This class Needs to inherit an Slick2d Shape, so for instance:
public class ShapeWithReference extends Rectangle{}
This class can have a list or a single object reference:
public class ShapeWithReference Rectangle{
Object reference = new String("hello"); //This is dirty and can be replaced by any object.
}
Since your new class is a Slick2D shape you can now find out whether it is contained by another shape:
Rectangle rec = new Rectangle();
if(rec.contains(ShapeWithReference)){
if(ShapeWithReference.reference instanceof String){
System.out.println((String)ShapeWithReference.reference);
}
}
Contains checks whether the shape really contains another shape. So they are not just intersecting. So that's the first part you check, the second one is whether the reference Attribute of the Shape is for e.g. a String. So if our first rectangle contains our new class and the reference of this class is type of a String this String is supposed to be written in to the console.
Hope this helps or gives you a hint.
EDIT:
public class SlickGame extends BasicGame {
static AppGameContainer appgc;
Rectangle rec;
ShapeWithReference swr;
public SlickGame(String title) {
super(title);
}
#Override
public void render(GameContainer container, Graphics g) throws SlickException {
}
#Override
public void init(GameContainer container) throws SlickException {
rec = new Rectangle(0, 0, 64, 64);
swr = new ShapeWithReference(0, 0, 1, 1);
}
#Override
public void update(GameContainer container, int delta) throws SlickException {
if(rec.intersects(swr)){
if(swr.reference instanceof String){
System.out.println((String)swr.reference);
}
else if(swr.reference instanceof Integer){
System.out.println((Integer)swr.reference);
}
else if(swr.reference instanceof Shape){
Shape temp = (Shape)swr.reference;
System.out.println(temp.getWidth());
}
}
}
public static void main(String[] args) {
try {
appgc = new AppGameContainer(new SlickGame("title"));
appgc.setDisplayMode(800, 600, false);
appgc.setTargetFrameRate(60);
appgc.setFullscreen(false);
appgc.start();
} catch (SlickException ex) {
ex.printStackTrace();
}
}
}
This is the code you should be able to copy & paste directly.
It does work for me, I'm not sure if I got your problem right but after the instanceof Operator you can just add the Class Name and check for it, I added some examples with an Integer and a Shape.
This is the 2nd class:
public class ShapeWithReference extends Rectangle {
private static final long serialVersionUID = 1L;
public ShapeWithReference(float x, float y, float width, float height) {
super(x, y, width, height);
}
Object reference = new String("hello");
}
Does this work for you?

How to rotate a bitmap with AffineTransform

I'm trying to create a simple program that displays a bitmap zombie picture and then rotates it around using AffineTransform and Thread. I followed the example I had to accomplish this, but whenever I run the program the zombie bitmap just rotates once and stops. Also, for some reason when I painted the zombie bitmap, the image is partially off the screen along the y-axis.
So my questions are: why is the bitmap not rotating and why is the bitmap off the screen.
Code is as follows:
import java.awt.*;// Graphics class
import java.awt.geom.*;
import java.net.*;//URL navigation
import javax.swing.*;//JFrame
import java.util.*;//Toolkit
public class BitMapZombies2 extends JFrame implements Runnable
{
private Image zombieOneRight;
Thread zombieRun;
public static void main (String[] args)
{
new BitMapZombies2();
}
public BitMapZombies2()
{
super("Bit Map Zombies..RUN FOR YOUR LIFE!!!");
setSize(800,600);
setVisible(true);
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
Toolkit Zkit = Toolkit.getDefaultToolkit();
zombieOneLeft = Zkit.getImage(getURL("_images/_production_images/zombie_1_left_75h.png"));
zombieOneRight = Zkit.getImage(getURL("_images/_production_images/zombie_1_right_75h.png"));
zombieRun = new Thread(this);
zombieRun.start();
}
AffineTransform zombieIdentity = new AffineTransform();
private URL getURL(String filename)
{
URL url = null;
try
{
url = this.getClass().getResource(filename);
}
catch (Exception e) {}
return url;
}
public void paint(Graphics z)
{
Graphics2D z2d = (Graphics2D) z;
AffineTransform ZombiePowered = new AffineTransform();
z2d.setColor(Color.BLACK);
z2d.fillRect(0,0, 800, 600);
ZombiePowered.setTransform(zombieIdentity);
ZombiePowered.rotate(2,37.5,37.5);
z2d.drawImage(zombieOneRight,ZombiePowered,this);
}
public void run()
{
Thread zT = Thread.currentThread();
while (zT == zombieRun)
{
try
{
Thread.sleep(500);
}
catch(InterruptedException e)
{
e.printStackTrace();
}
repaint();
}
}
}
Appreciate any help I can get on this.
Commenting your code:
AffineTransform ZombiePowered = new AffineTransform();//Create an Id. transform
ZombiePowered.setTransform(zombieIdentity);//Set it as a copy of an Id. transform
ZombiePowered.rotate(2, 37.5, 37.5);//Concatenate the rotation with the Id. transform
z2d.drawImage(zombieOneRight, ZombiePowered, this);//Apply the rotation
So your always rotating 2rads your image. If you do this assignment at the end of the paint method:
zombieIdentity = ZombiePowered;
the next time you paint the image it will be rotate 2rads more.
About the issues with the position, take a look at rotate javadoc:
Concatenates this transform with a transform that rotates coordinates
around an anchor point. This operation is equivalent to translating
the coordinates so that the anchor point is at the origin (S1), then
rotating them about the new origin (S2), and finally translating so
that the intermediate origin is restored to the coordinates of the
original anchor point (S3).
This operation is equivalent to the following sequence of calls:
translate(anchorx, anchory); // S3: final translation
rotate(theta); // S2: rotate around anchor
translate(-anchorx, -anchory); // S1: translate anchor to origin
Hope it helps.
Once you've created your transformation, you need to apply it to the graphics context...
public void paint(Graphics z)
{
//...
z2d.setTransform(ZombiePowered);
//...
}
Once you apply a transformation, it will effect everything painted to the Graphics context after it so you need to reset it or referse it. There's lots of ways to do this, but the simplest would be to create a copy of the Graphics context and simply dispose of it when you no longer need it...
public void paint(Graphics z)
{
Graphics2D z2d = (Graphics2D) z.create();
//...
z2d.dispose();
}
Also, this is just me, but I'd be creating a new instance of the AffineTransform, these things are to easy to completely screw up...

How to tell when Graphics.drawImage() has actually completed

This is my first time asking a question on here, and I'm hoping I get an answer or an idea that will help me.
I am drawing a large image and scaling it down with drawImage(). I then immediately draw another image with drawImage() that I expect to be drawn on top of the previous one (second). The problem is that drawImage returns immediately, even if it takes ~50 ms to scale and render the first image. Most of the time the second image ends up underneath the first one because it's painted first while the big first one is being processed. Basically is there anyway to force drawImage() to block until it's done, or to somehow check when it has completed?
I'm aware of the ImageObserver parameter, which works fine when downloading an image from the Internet or something, but when using an already-loaded BufferedImage, it never fires ImageUpdate() just after scaling and drawing. Basically since the first image is already "loaded" it never contacts the ImageObserver, it just takes like ~50 ms in it's own thread to process, never notifying when it completes.
Does anyone know how to either force it to block or wait until it's completely done scaling and blitting an image? And obviously using Thread.sleep(xx) is a complete hack and not viable due to differences between computer speeds. All this rendering is happened on the Event thread inside the paint(Graphics g) method.
Thanks!
EDIT: The following is code I currently have to give you an idea of the issue:
public void paint(Graphics window)
{
window.setColor(Color.WHITE);
window.fillRect(0, 0, Settings.width * Settings.aaFactor, Settings.height * Settings.aaFactor);
Graphics2D window2D = (Graphics2D) window;
window2D.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
window2D.drawImage(this.image, 0, 0, Settings.width, Settings.height, null);
try
{
Thread.sleep(50);
}
catch (InterruptedException e)
{
e.printStackTrace();
}
window2D.drawImage(this.image2, 0, 0, null);
repaint();
}
EDIT 2: To better explain the problem I'm talking about, I made some sample code that does better what I'm trying to explain. Run it and you will see it flickering where sometimes the first image is on bottom (like it's supposed to be), but most of the time it will be one top (second), which is wrong. Just change the File paths to a small image and a large image.
public class Main extends Applet implements ImageObserver
{
private BufferedImage imageA;
private BufferedImage imageB;
#Override
public void init()
{
try
{
this.imageA = ImageIO.read(new File("C:\\LargeImage.jpg"));
this.imageB = ImageIO.read(new File("C:\\SmallImage.jpg"));
}
catch (IOException e)
{
e.printStackTrace();
}
}
#Override
public void update(Graphics g)
{
paint(g);
}
#Override
public void paint(Graphics g)
{
Graphics2D w = (Graphics2D) g;
w.setRenderingHint(RenderingHints.KEY_INTERPOLATION, RenderingHints.VALUE_INTERPOLATION_BICUBIC);
w.drawImage(this.imageA, 0, 0, 50, 50, this);// This takes a while to do (scaling down and drawing)...
w.drawImage(this.imageB, 10, 10, null);// While this is drawn quickly, before A is done.
repaint();
}
#Override
public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
{
System.out.println("ImageObserver fired, done drawing image. NEVER CALLED!");
return false;
}
}
The last argument to drawImage (where you pass null) is an ImageObserver. If you provide your own implementation of that interface (see JavaDoc), you will be informed when the image has been actually drawn.
It is impossible to know when Swing will actually render the contents of a Graphics object to the screen. What is know is it won't happen until AFTER the paint methods return (as the Graphics object hasn't been finalised for rendering until it does).
What you should do is let the Component you are painting to make the decision as to when something needs to updated, this is the way it was designed...(Component implements ImageObserver)
The below example continuously re-scales the master background image as the frame is resized
public class TestPaint03 {
public static void main(String[] args) {
new TestPaint03();
}
public TestPaint03() {
EventQueue.invokeLater(new Runnable() {
#Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (Exception ex) {
}
JFrame frame = new JFrame("Test");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(new PaintPane());
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class PaintPane extends JPanel {
private BufferedImage background;
private BufferedImage foreground;
private Image scaled;
public PaintPane() {
try {
background = ImageIO.read(new File("/path/to/background/image));
foreground = ImageIO.read(new File("path/to/foreground/image"));
} catch (Exception e) {
}
}
#Override
public void invalidate() {
scaled = null;
super.invalidate();
}
#Override
public Dimension getPreferredSize() {
return new Dimension(200, 200);
}
#Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
if (background != null) {
if (scaled == null) {
int size = Math.min(getWidth(), getHeight());
scaled = background.getScaledInstance(-1, size, Image.SCALE_SMOOTH);
}
int x = (getWidth() - scaled.getWidth(this)) / 2;
int y = (getHeight() - scaled.getHeight(this)) / 2;
g.drawImage(scaled, x, y, this);
x = (getWidth() - foreground.getWidth()) / 2;
y = (getHeight() - foreground.getHeight()) / 2;
g.drawImage(foreground, x, y, this);
}
}
}
}
While I'm sure you have your reasons, personally I would avoid Applet in favor of JApplet and in fact, I would personally avoid applets or together. I started my career coding applets, they are simply a pain, especially when all you're trying to do is test an idea.

How do you toggle an image with a button event in Slick?

So I am trying to get a simple GUI setup for my teams game we are starting and I'm trying to make a drop down inventory using "I" as the hot key for it and it drops fine but I can't seem to figure out a way without using a different key to make it retract or in essence "un" draw the image'
public void render(GameContainer gc, StateBasedGame sbg, Graphics g) throws
SlickException {
mapHud.draw(440, 1);
hotBar.draw(160, 454);
if(inv){
inventory.draw(-40, 1);
}
}
#Override
public void update(GameContainer gc, StateBasedGame sbg, int delta) throws SlickException {
Input input = gc.getInput();
if(input.isKeyPressed(Input.KEY_I)){
inv = true;
}
if(input.isKeyPressed(Input.KEY_ESCAPE)) {
sbg.enterState(0);
}
}
Try something like this:
if(input.isKeyPressed(Input.KEY_I)){
inv = !inv;
}

Slick2D smooth movement of object with cursor keys

I'm playing around with Slick2D and I'm running into a problem when trying to move a simple rectangle with the cursor keys.
Functionality wise, the code works. However, if you keep one of the cursor keys pressed, every now and then there is a little hick-up in the movement wen looking at the screen.
Can anyone suggest a code improvement to make the rectangle move smoothly?
Here is the test code I used:
public class SlickGame extends BasicGame {
// ==================================================================================
// Fields
// ==================================================================================
private Rectangle mPlayer;
// ==================================================================================
// Constructor
// ==================================================================================
public SlickGame() {
super("SlickGame");
}
// ===========================================================
// Methods for/from SuperClass/Interfaces
// ===========================================================
#Override
public void init(GameContainer pGameContainer) throws SlickException {
// create the player centered on the screen
mPlayer = new Rectangle(pGameContainer.getWidth()/2 - 20, pGameContainer.getHeight()/2 - 20, 40, 40);
}
#Override
public void update(GameContainer pGameContainer, int pDelta) throws SlickException {
Input input = pGameContainer.getInput();
int speed = 200;
float distance = speed * ((float)pDelta/1000);
if (input.isKeyDown(Input.KEY_LEFT)) {
mPlayer.setX(mPlayer.getX() - distance);
}
if (input.isKeyDown(Input.KEY_RIGHT)) {
mPlayer.setX(mPlayer.getX() + distance);
}
if (input.isKeyDown(Input.KEY_UP)) {
mPlayer.setY(mPlayer.getY() - distance);
}
if (input.isKeyDown(Input.KEY_DOWN)) {
mPlayer.setY(mPlayer.getY() + distance);
}
}
#Override
public void render(GameContainer pGameContainer, Graphics pGraphics) throws SlickException {
pGraphics.fill(mPlayer);
}
// ==================================================================================
// Methods
// ==================================================================================
public static void main(String[] args) {
try {
// create the game's container app
AppGameContainer container = new AppGameContainer(new SlickGame());
// adjust the resolution and disable fullscreen
container.setDisplayMode(800, 600, false);
// specify desired FPS
container.setTargetFrameRate(60);
// start the game
container.start();
}
catch (SlickException e ) {
e.printStackTrace();
}
}
}
Thanks, naughty_hacker. Adding container.setVSync(true); did the trick.

Categories