I have a difficult situation.
I'm making a 2D game and I'm on the step
of integrating box2Dlights part.
But when i'm rendering my RayHandler, I have a black screen.
Here is another image, where I don't render my lights. There is no lights now.
I need to have collision of Box2D and Box2Dlights mixed together.
Please note:
All my boxes are made in units, equal to 1, so that one room is 16 squares length.
All entire world is zoomed by setToOrtho((16 - 1.875f) / Gdx.graphics.getHeight()), where 16 is tile size.
If I scaled my tile size, I would like to have this stuff work.
All code is complicated so I send the only GameScreen and GameMap classes for now:
#Override
public void show() {
InstanceVars inst = InstanceVars.getInstance();
inst.world = new World(new Vector2(0, 0f), true);
inst.engine = new Engine();
inst.handler = new RayHandler(inst.world);
LevelCreator creator = new LevelCreator("level_def.cfg");
try {
gameWorld = creator.createNewLevel();
gameWorld.start();
} catch (FileCorruptedException e) {
e.printStackTrace();
}
}
#Override
public void render(float delta) {
gameWorld.render();
}
#Override
public void resize(int width, int height) {
gameWorld.resize(width, height);
}
#Override
public void dispose() {
gameWorld.dispose();
InstanceVars.getInstance().dispose();
}
for the GameScreen.java
and
private World physWorld = InstanceVars.getInstance().world;
private Box2DDebugRenderer physRender = new Box2DDebugRenderer();
private OrthographicCamera cam = new OrthographicCamera();
private RayHandler lights = new RayHandler(physWorld);
private PlayerController controls;
private float STD_ZOOM = ((float) CELL_SIZE + 16) / Gdx.graphics.getHeight();
private Body playerBody;
public GameMap() {
cam.zoom = STD_ZOOM;
}
public void start() {
GameObject player = (GameObject) getProperties().get("ent_player");
playerBody = player.getComponent(PhysicsComponent.class).getBody();
controls = new PlayerController();
Gdx.input.setInputProcessor(controls);
physWorld.setContactListener(new CollisionInteractor(InstanceVars.getInstance().engine));
PointLight light = new PointLight(lights, 1000, Color.GOLDENROD, 500, playerBody.getPosition().x, playerBody.getPosition().y);
}
public void render() {
updatePlayer();
physWorld.step(1/60f, 8, 2);
updateCamera();
physRender.render(physWorld, cam.combined);
// lights.updateAndRender();
}
private void updatePlayer() {
if (controls.up) playerBody.setLinearVelocity(playerBody.getLinearVelocity().x, -controls.speed);
else playerBody.setLinearVelocity(playerBody.getLinearVelocity().x, controls.down ? controls.speed : 0);
if (controls.down) playerBody.setLinearVelocity(playerBody.getLinearVelocity().x, controls.speed);
else playerBody.setLinearVelocity(playerBody.getLinearVelocity().x, controls.up ? -controls.speed : 0);
if (controls.left) playerBody.setLinearVelocity(-controls.speed, playerBody.getLinearVelocity().y);
else playerBody.setLinearVelocity(controls.right ? controls.speed : 0, playerBody.getLinearVelocity().y);
if (controls.right) playerBody.setLinearVelocity(controls.speed, playerBody.getLinearVelocity().y);
else playerBody.setLinearVelocity(controls.left ? -controls.speed : 0, playerBody.getLinearVelocity().y);
}
public void resize(float width, float height) {
STD_ZOOM = ((float) CELL_SIZE - 1.875f) / Gdx.graphics.getHeight();
cam.setToOrtho(true, width, height);
}
private void updateCamera() {
cam.position.set(playerBody.getPosition(), 0);
cam.update();
}
public void dispose() {
super.dispose();
physWorld.dispose();
physRender.dispose();
}
for GameMap.java.
If you need more details, don't be afraid to ask.
I cannot solve the problem on my own.
Related
I wanted to create a simple 30x30 isometric tiled map and add a listener to be able to click on the tiles. I looked up a lot of the articles and posts here but none of them helped me.
My issue is, i have a viewport, 30x17, a camera, a stage and a tiled map with tileWidth = 32 and tileHeight = 16 pixels.
Now when i render the tiled map it looks fine.
When i click on stage and try to get the world coordinates i see some really weird coordinates.
This is the code:
private static final float TILE_WIDTH = 32;
private static final float TILE_HEIGHT = 16;
private OrthographicCamera camera;
private Viewport viewport;
private Stage stage;
private IsometricTiledMapRenderer isometricTiledMapRenderer;
private Matrix4 isoTransform;
private Matrix4 invIsotransform;
public void load(AssetManagerLoaderV2 assetManagerLoader) {
assetManagerLoader.load();
init();
camera = new OrthographicCamera();
viewport = new FitViewport(30, 17, camera);
stage = new Stage(viewport);
TiledMap tiledMap = new TiledMapGenerator(assetManagerLoader).generate(30, 30);
isometricTiledMapRenderer = new IsometricTiledMapRenderer(tiledMap, 1/32f);
stage.addListener(new InputListener() {
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
System.out.println(screenToCell(x, y));
return true;
}
});
}
#Override
public void show() {
Gdx.input.setInputProcessor(stage);
}
#Override
public void render(float delta) {
DrawUtils.clearScreen();
viewport.apply();
isometricTiledMapRenderer.setView(camera);
isometricTiledMapRenderer.render();
}
#Override
public void resize(int width, int height) {
stage.getViewport().update(width, height, true);
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void hide() {
}
#Override
public void dispose() {
isometricTiledMapRenderer.dispose();
stage.dispose();
}
public void init () {
//create the isometric transform
isoTransform = new Matrix4();
isoTransform.idt();
isoTransform.translate(0.0f, 0.25f, 0.0f);
isoTransform.scale((float)(Math.sqrt(2.0) / 2.0), (float)(Math.sqrt(2.0) / 4.0), 1.0f);
isoTransform.rotate(0.0f, 0.0f, 1.0f, -45.0f);
//... and the inverse matrix
invIsotransform = new Matrix4(isoTransform);
invIsotransform.inv();
}
public Vector2 worldToCell(float x, float y) {
float halfTileWidth = TILE_WIDTH * 0.5f;
float halfTileHeight = TILE_HEIGHT * 0.5f;
float row = (1.0f/2) * (x/halfTileWidth + y/halfTileHeight);
float col = (1.0f/2) * (x/halfTileWidth - y/halfTileHeight);
return new Vector2((int)col,(int)row);
}
public Vector2 screenToWorld(float x, float y){
Vector3 touch = new Vector3(x,y,0);
camera.unproject(touch);
touch.mul(invIsotransform);
touch.mul(isoTransform);
return new Vector2(touch.x,touch.y);
}
public Vector2 screenToCell(float x, float y) {
Vector2 world = screenToWorld(x,y);
world.y -= TILE_HEIGHT *0.5f;
return worldToCell(world.x,world.y);
}
Does anyone have an idea how to write worldToCell to get the proper coordinates?
I found the issue, i was missing one step.
This is what touchDown should look like:
#Override
public boolean touchDown(InputEvent event, float x, float y, int pointer, int button) {
Vector2 newCoords = stage.stageToScreenCoordinates(new Vector2(x, y));
System.out.println(screenToCell(newCoords.x, newCoords.y));
return true;
}
I need to convert stage coordinates to screen coordinates, now this code is working.
I am using box2dlights in my project and there seem to be an issue. When I actually use RayHandler in the program, only the light is drawn but no textures. And so when I remove RayHandler from the render loop it all works fine. I want the light to be drawn and then textures to be drawn above it. How do I reach that?
This is the code:
public class GameScreen implements Screen {
private Core core;
private SpriteBatch batch;
private Sprite spiderSprite;
private OrthographicCamera camera;
private RayHandler rayHandler;
private Box2DDebugRenderer debugRenderer;
private World world;
private Body spider, prop;
private PointLight spiderLight;
private Stage stage;
private boolean paused, lost, check;
private int pointsCount;
private float time;
public GameScreen(Core c) {
core = c;
stage = new Stage();
batch = new SpriteBatch();
camera = new OrthographicCamera();
camera.setToOrtho(false, core.SCREEN_WIDTH, core.SCREEN_HEIGHT);
batch.setProjectionMatrix(camera.combined);
debugRenderer = new Box2DDebugRenderer();
spiderSprite = core.chars.createSprite("spider");
world = new World(new Vector2(.0f, -10.0f), true);
BodyDef spiderDef = new BodyDef();
spiderDef.type = BodyDef.BodyType.DynamicBody;
spiderDef.position.set(core.SCREEN_WIDTH / 2, core.SCREEN_HEIGHT / 2);
spider = world.createBody(spiderDef);
CircleShape shape = new CircleShape();
shape.setRadius(core.SCREEN_WIDTH / 15);
spider.createFixture(shape, .1f);
BodyDef propDef = new BodyDef();
propDef.type = BodyDef.BodyType.StaticBody;
propDef.position.set(core.SCREEN_WIDTH / 2, core.SCREEN_HEIGHT);
prop = world.createBody(propDef);
CircleShape propShape = new CircleShape();
propShape.setRadius(0.1f);
prop.createFixture(propShape, 1.0f);
RopeJointDef rope = new RopeJointDef();
rope.bodyA = spider;
rope.bodyB = prop;
rope.maxLength = core.SCREEN_HEIGHT / 2;
world.createJoint(rope);
rayHandler = new RayHandler(world);
rayHandler.setAmbientLight(.5f);
spiderLight = new PointLight(rayHandler, 100, Color.WHITE, core.SCREEN_WIDTH, 100, 100);
spiderLight.attachToBody(spider);
}
#Override
public void show() {
Gdx.input.setInputProcessor(stage);
stage.addAction(Actions.fadeIn(0.85f));
}
#Override
public void render(float delta) {
clearScreen();
batch.setProjectionMatrix(camera.combined);
batch.begin();
if (!lost && !paused) {
updateWorld();
updateSpider();
}
drawSpider();
stage.act();
stage.draw();
batch.end();
}
private void clearScreen() {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
}
private void updateSpider() {
//spider.setLinearVelocity(Gdx.input.getAccelerometerX() > 0 ? 50.0f : -50.0f, 0.0f);
float angle = MathUtils.radiansToDegrees * MathUtils.atan2(core.SCREEN_HEIGHT - spider.getPosition().y, core.SCREEN_WIDTH / 2 - spider.getPosition().x) - 90;
spiderSprite.setPosition(spider.getPosition().x, spider.getPosition().y);
spiderSprite.setRotation(angle);
}
private void drawSpider() {
spiderSprite.draw(batch);
rayHandler.render();
}
private void updateWorld() {
world.step(1/60f, 6, 2);
rayHandler.setCombinedMatrix(camera);
rayHandler.update();
time += Gdx.graphics.getDeltaTime();
}
}
I also removed a redundant part of the code which is not connected with the issue.
Stage has it's own batch with it's own .begin() and .end(). You should call batch.end(); before calling stage.draw();
I found it out. RayHandler.render() must not be invoked between batch.begin() and batch.end().
I have two screens, a MainActivity in my core folder, that has the render() method split into a few switch cases. On game-over, this part of the switch case gets triggered, which calls the render part of my game-over class:
case STOPPED:
// Exit and clean the game
gameOverScreen.render(Gdx.graphics.getDeltaTime());
break;
...
This is my GameOverScreen class:
public class GameOverScreen implements Screen {
private SpriteBatch gameOverBatch;
private FreeTypeFontGenerator gameOverFontGen;
private FreeTypeFontGenerator.FreeTypeFontParameter gameOverLogoParam;
private FreeTypeFontGenerator.FreeTypeFontParameter gameOverButtonParam;
private final MainActivity mainActivity;
private OrthographicCamera camera;
private BitmapFont bitmapLogoFont;
private BitmapFont bitmapButtonFont;
private Button exitGameButton;
private Button gameRestartButton;
private Sound buttonSound;
private Stage stage;
private float w;
private float h;
// Constructor
public GameOverScreen(MainActivity mainActivity) {
w = Gdx.graphics.getWidth();
h = Gdx.graphics.getHeight();
gameOverBatch = new SpriteBatch();
this.mainActivity = mainActivity;
camera = new OrthographicCamera();
camera.setToOrtho(false, 300, 300);
// Instantiate the font for this screen from file
gameOverFontGen = new FreeTypeFontGenerator(Gdx.files.internal("fonts/SF_Wonder_Comic.ttf"));
gameOverLogoParam = new FreeTypeFontGenerator.FreeTypeFontParameter();
gameOverLogoParam.size = 110;
gameOverButtonParam = new FreeTypeFontGenerator.FreeTypeFontParameter();
gameOverButtonParam.size = 40;
// Font for the logo
bitmapLogoFont = new BitmapFont();
bitmapLogoFont = gameOverFontGen.generateFont(gameOverLogoParam);
// Font for the buttons
bitmapButtonFont = new BitmapFont();
bitmapButtonFont = gameOverFontGen.generateFont(gameOverButtonParam);
// Instantiate the buttonSound
buttonSound = Gdx.audio.newSound(Gdx.files.internal("sounds/pauseBtn_sound.ogg"));
/*************************************** Create a Stage *******************************************/
stage = new Stage();
// Add some actors as the buttons
exitGameButton = new Button(new TextureRegionDrawable(
new TextureRegion(new Texture(Gdx.files.internal("images/off_red.png")))),
new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("images/off_white.png")))));
//exitGameButton.setX((w, 150));
//pauseButton.setY(flipCoordinates(h, 150));
exitGameButton.setOrigin(exitGameButton.getWidth() / 2, exitGameButton.getHeight() / 2);
exitGameButton.setBounds(w / 2 + 100, h / 2 - 60, exitGameButton.getWidth(), exitGameButton.getHeight());
exitGameButton.act(Gdx.graphics.getDeltaTime());
stage.addActor(exitGameButton);
exitGameButton.addListener(new ChangeListener() {
#Override
public void changed (ChangeEvent event, Actor actor) {
buttonSound.play();
}
});
// Add some actors as the buttons
TextButton.TextButtonStyle restartStyle = new TextButton.TextButtonStyle();
restartStyle.font = bitmapButtonFont;
restartStyle.up = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("images/back_red.png"))));
restartStyle.down = new TextureRegionDrawable(new TextureRegion(new Texture(Gdx.files.internal("images/back_white.png"))));
gameRestartButton = new Button(new TextButton.TextButtonStyle(restartStyle));
gameRestartButton.setOrigin(gameRestartButton.getWidth() / 2, gameRestartButton.getHeight() / 2);
gameRestartButton.setBounds(w / 2 - 100, h / 2 - 60, gameRestartButton.getWidth(), gameRestartButton.getHeight());
gameRestartButton.act(Gdx.graphics.getDeltaTime());
stage.addActor(gameRestartButton);
// Capture the event listener for the return button
gameRestartButton.addListener(new ChangeListener() {
#Override
public void changed(ChangeEvent event, Actor actor) {
// Do something on restart
//MainActivity.state = MainActivity.State.RUN;
Gdx.app.log("GameRestartButton", " has been pressed");
}
});
gameRestartButton.act(Gdx.graphics.getDeltaTime());
//stage.addActor(exitGameButton);
//stage.addActor(gameRestartButton);
}
#Override
public void render(float delta) {
Gdx.gl.glClearColor(0, 0, 0, 0);
Gdx.gl.glClear(GL20.GL_COLOR_BUFFER_BIT);
camera.update();
gameOverBatch.begin();
bitmapLogoFont.setColor(Color.RED);
bitmapLogoFont.draw(gameOverBatch, "Game Over", w / 2 - 210, h / 2 + 150f);
gameOverBatch.end();
exitGameButton.act(Gdx.graphics.getDeltaTime());
stage.act(Gdx.graphics.getDeltaTime());
stage.draw();
}
#Override
public void resize(int width, int height) {
}
#Override
public void show() {
}
#Override
public void hide() {
}
#Override
public void pause() {
}
#Override
public void resume() {
}
#Override
public void dispose() {
gameOverFontGen.dispose();
}
}
In GameOverScreen constructor I have two buttons (exitGameButton and gameReturnButton) I'd like to be able to trigger their event-listeners, but I can't seem to be able to do it. Neither of my buttons responds to the event listener. What am I doing wrong? Do I need to add something else on to my MainActivity class for these buttons to work ? Thanks much.
I figured it out, on the second screen I was missing from the constructor this: Gdx.input.setInputProcessor(stage); , of course, that only works if a stage has been previously created.
try this in your class GameOverScreen
.//
public Stage getStageGameOverScreen(){
return this.stage;
}
your Case:
case STOPPED:
// Exit and clean the game
Gdx.input.setInputProcessor(gameOverScreen.getStageGameOverScreen());
gameOverScreen.render(Gdx.graphics.getDeltaTime());
break;
...
I've made a simple Media Player for an application I'm working on, the problem is that I thought that you could simply integrate JavaFX into Swing. Which is not the case. I have been searching for a solution to this problem and tried to use this website: http://docs.oracle.com/javafx/2/swing/jfxpub-swing.htm
The problem is that even though I have the website that explains how to put the code together, I still don't understand how. Here is the mediaplayer and I plan to integrate it into my Swing code, so that I can call the media player when a button is clicked. Here is all my code for the media player and if anyone can share some light on how to integrate it into my Swing code i.e my GUI, I would probably have to kiss you through the computer.
public class Player extends Application{
private boolean atEndOfMedia = false;
private final boolean repeat = false;
private boolean stopRequested = false;
private Duration duration;
private Label playTime;
private Slider volumeSlider;
#Override
public void start(final Stage stage) throws Exception {
stage.setTitle("Movie Player");//set title
Group root = new Group();//Group for buttons etc
final Media media = new Media("file:///Users/Paul/Downloads/InBruges.mp4");
final MediaPlayer playa = new MediaPlayer(media);
MediaView view = new MediaView(playa);
//Slide in and out and what causes that.
final Timeline slideIn = new Timeline();
final Timeline slideOut = new Timeline();
root.setOnMouseEntered(new javafx.event.EventHandler<javafx.scene.input.MouseEvent>() {
#Override
public void handle(MouseEvent t) {
slideIn.play();
}
});
root.setOnMouseExited(new javafx.event.EventHandler<javafx.scene.input.MouseEvent>() {
#Override
public void handle(MouseEvent t) {
slideOut.play();
}
});
final VBox vbox = new VBox();
final Slider slider = new Slider();
final Button playButton = new Button("|>");
root.getChildren().add(view);
root.getChildren().add(vbox);
vbox.getChildren().add(slider);
vbox.getChildren().add(playButton);
vbox.setAlignment(Pos.CENTER);
Scene scene = new Scene(root, 400, 400, Color.BLACK);
stage.setScene(scene);
stage.show();
// Play/Pause Button
playButton.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent e) {
Status status = playa.getStatus();
if (status == Status.UNKNOWN || status == Status.HALTED)
{
// don't do anything in these states
return;
}
if ( status == Status.PAUSED
|| status == Status.READY
|| status == Status.STOPPED)
{
// rewind the movie if we're sitting at the end
if (atEndOfMedia) {
playa.seek(playa.getStartTime());
atEndOfMedia = false;
}
playa.play();
} else {
playa.pause();
}
}
});
//Listeners and Shit for Play Button
playa.setOnPlaying(new Runnable() {
#Override
public void run() {
if (stopRequested) {
playa.pause();
stopRequested = false;
} else {
playButton.setText("||");
}
}
});
playa.setOnPaused(new Runnable() {
#Override
public void run() {
playButton.setText(">");
}
});
playa.play();
playa.setOnReady(new Runnable() {
#Override
public void run(){
int v = playa.getMedia().getWidth();
int h = playa.getMedia().getHeight();
stage.setMinWidth(v);
stage.setMinHeight(h);
vbox.setMinSize(v, 100);
vbox.setTranslateY(h-50);
//slider and graphical slide in/out
slider.setMin(0.0);
slider.setValue(0.0);
slider.setMax(playa.getTotalDuration().toSeconds());
slideOut.getKeyFrames().addAll(
new KeyFrame(new Duration(0),
new KeyValue(vbox.translateYProperty(), h-100),
new KeyValue(vbox.opacityProperty(), 0.9)
),
new KeyFrame(new Duration(300),
new KeyValue(vbox.translateYProperty(), h),
new KeyValue(vbox.opacityProperty(), 0.0)
)
);
slideIn.getKeyFrames().addAll(
new KeyFrame(new Duration(0),
new KeyValue(vbox.translateYProperty(), h),
new KeyValue(vbox.opacityProperty(), 0.0)
),
new KeyFrame(new Duration(300),
new KeyValue(vbox.translateYProperty(), h-100),
new KeyValue(vbox.opacityProperty(), 0.9)
)
);
}
});
//Slider being current and ability to click on slider.
playa.currentTimeProperty().addListener(new ChangeListener<Duration>(){
#Override
public void changed(ObservableValue<? extends Duration> observableValue, Duration duration, Duration current){
slider.setValue(current.toSeconds());
}
});
slider.setOnMouseClicked(new javafx.event.EventHandler<javafx.scene.input.MouseEvent>() {
#Override
public void handle(javafx.scene.input.MouseEvent t) {
playa.seek(Duration.seconds(slider.getValue()));
}
});
}
Use JFXPanel:
public class Test {
private static void initAndShowGUI() {
// This method is invoked on Swing thread
JFrame frame = new JFrame("FX");
final JFXPanel fxPanel = new JFXPanel();
frame.add(fxPanel);
frame.setVisible(true);
Platform.runLater(new Runnable() {
#Override
public void run() {
initFX(fxPanel);
}
});
}
private static void initFX(JFXPanel fxPanel) {
// This method is invoked on JavaFX thread
Scene scene = createScene();
fxPanel.setScene(scene);
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
initAndShowGUI();
}
});
}
}
where method createScene() is start(final Stage stage) from your code.
Just instead of putting scene to stage you return it.
I've written an app that custom draws everything inside paint() based on fixed pixel positions. Then I disabled resize of the frame so its always visible.
However, now I would like to be able to resize it but I dont want to change my drawling code. I was hoping I could grab the 300x300 square of the Graphics g object and resize it to the JFrame current size after all of my drawling code, but I have no idea what I'm doing.
Here sample code. In this I want the 100x100 square to remain in the middle, proportionate to the resized JFrame:
package DrawAndScale;
import java.awt.Color;
import java.awt.Graphics;
public class DASFrame extends javax.swing.JFrame {
public DASFrame() {
setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
this.setSize(300, 300);
}
public static void main(String args[]) {
java.awt.EventQueue.invokeLater(new Runnable() {
public void run() {
new DASFrame().setVisible(true);
}
});
}
#Override
public void paint(Graphics g) {
g.setColor(Color.BLACK);
g.fill3DRect(100, 100, 100, 100, true);
}
}
Thanks.
Assuming you rename your method that paints for 300x300 as paint300, define a buffered image:
#Override public void paint(Graphics g) {
Image bufferImage = createImage(300, 300); // empty image
paint300(bufferImage.getGraphics()); // fill the image
g.drawImage(bufferImage, 0, 0, null); // send the image to graphics device
}
Above is when you want to draw at full size (300x300).
If your window is resized:
#Override public void paint(Graphics g) {
Image bufferImage = createImage(300, 300);
paint300(bufferImage.getGraphics());
int width = getWidth();
int height = getHeight();
CropImageFilter crop =
new CropImageFilter((300 - width)/2, (300 - height)/2 , width, height);
FilteredImageSource fis = new FilteredImageSource(bufferImage, crop);
Image croppedImage = createImage(fis);
g.drawImage(croppedImage, 0, 0, null);
}
The new classes are from from java.awt.image.*.
I didn't test this code. It's just to send you in the right direction.
if you want to painting Custom paint then look for JLabel or JPanel and including Icon/ImageIcon inside, simple example about that
import java.awt.*;
import javax.swing.*;
public class MainComponentPaint extends JFrame {
private static final long serialVersionUID = 1L;
public MainComponentPaint() {
setTitle("Customize Preffered Size Test");
setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
}
public void display() {
add(new CustomComponent());
pack();
setMinimumSize(getSize());
setPreferredSize(getSize());
SwingUtilities.invokeLater(new Runnable() {
#Override
public void run() {
setVisible(true);
}
});
}
public static void main(String[] args) {
MainComponentPaint main = new MainComponentPaint();
main.display();
}
}
class CustomComponent extends JComponent {
private static final long serialVersionUID = 1L;
#Override
public Dimension getPreferredSize() {
return new Dimension(50, 50);
}
#Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
int w = getWidth();
int h = getHeight();
for (int i = 0; i < Math.max(w, h); i += 20) {
g.drawLine(i, 0, i, h);
g.drawLine(0, i, w, i);
}
}
}
Not an expert, but you could just scale the Graphics2D object (the passed Graphics is in fact a Graphics2D instance), where the x and y ratios are the ratios of the fixed size you chose to draw and the actual size of the frame.
See http://download.oracle.com/javase/6/docs/api/java/awt/Graphics2D.html#scale%28double,%20double%29
You could do this with some math.
public void paint(Graphics g){
int height = 100;
int width = 100;
int x = (this.getWidth() / 2) - (width / 2);
int y = (this.getHeight() / 2) - (height / 2);
g.setColor(Color.BLACK);
g.fill3DRect(x, y, width, height, true);
}
Or if you wanted to keep the width and height of the box with the same proportion, use int width = this.getWidth() / 3; and int height = this.getHeight() / 3.
The other option is to use Graphics2D.scale(), as JB pointed out, the passed Graphics object is actually a Graphics2D object.