This site requires JavaScript, please enable it in your browser!
Greenfoot back
getreides
getreides wrote ...

2014/8/3

setColor won't work

getreides getreides

2014/8/3

#
For a shooter, I've created a class that simulates the tracers (TracerMGun) of invisible projectiles (MGun). In doing so, when firing each act-cycle the objects of MGun create a new object of class TracerMGun at the respective X/Y-position. In order to simulate the dissolving of the tracers, I've implemented three methods in TracerMGun- class: - fadeTransparency (reduces the transparency value of each object) - SizingDownTracer (scales the size of each object) - changeColor (is supposed to change the green component of the object). The first two methods work perfectly fine, but the changeColor doesn't at all, though its code is written according to the same principle fadeTransparency/fadeTransparency are. Does anyone know why? Here's the full code of the TracerMGun:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
import greenfoot.*;  // (World, Actor, GreenfootImage, Greenfoot and MouseInfo)
import java.awt.Color;
 
 
public class TracerMGun extends MGun
{
    private int transparency = 255;
    private int GreenComponent = 0;
    private int BlueComponent = 0;
    Color TracerColor = new Color (255, GreenComponent, BlueComponent);
 
    private int TracerSize = 4;
    private int SizeDownTracer;
     
    public TracerMGun ()
    {  
        GreenfootImage TracerMGunImage = new GreenfootImage (TracerSize, TracerSize);
        TracerMGunImage.drawOval (0, 0, TracerSize, TracerSize);
        TracerMGunImage.setColor (TracerColor);
        TracerMGunImage.fillOval (0, 0, TracerSize, TracerSize);
        setImage (TracerMGunImage);
        getImage().setTransparency(transparency);
    }
     
    public void act()
    {
       fadeTransparency ();
       SizingDownTracer ();
       changeColor(); 
    }
     
            public void fadeTransparency ()
            {
               if (transparency == 0 || TracerSize <= 1)
               {
                   getWorld().removeObject(this);
               }
               else if (transparency > 0)
               
               transparency = transparency - 5;
               getImage().setTransparency(transparency);
               setLocation (getX(), getY() - 1);
               }
            }
     
            public void SizingDownTracer()
            {
                SizeDownTracer++;
                if (SizeDownTracer % 10 == 0)
                {
                    TracerSize --;
                    getImage().scale(TracerSize, TracerSize);
                }
            }
                        
            public void changeColor()
            {
                GreenComponent = GreenComponent + 8;
                getImage().setColor(TracerColor);
            }
             
}
danpost danpost

2014/8/3

#
Line 58 changes the value of the int field 'GreenComponent'. The 'TracerColor' object is not altered by any change in the value of this field. You need to create a new Color and then set the new color to the TracerColor field. After that, you still need to re-create the image using that new TracerColor value and set the image of the actor to the new image. You may want to put what you have in your constructor in a separate method and call it from the constructor so you can call it from the 'changeColor' method as well (like an 'updateImage' method). BTW, 'setColor' only specifies a new drawing color for an image; it does not, in itself, change the image. It is like setting down one pen and picking another up of the color specified that other methods will use to actually draw with.
getreides getreides

2014/8/3

#
Thanks for your superquick reply, I've changed changeColor() to this...
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public void changeColor()
{
    GreenComponent = GreenComponent + 8;
    Color currentColor = new Color (255, GreenComponent, BlueComponent);
    int currentTransparency = this.transparency;
    int currentTracerSize = this.TracerSize;
     
    GreenfootImage CurrentTracerMGunImage = new GreenfootImage (currentTracerSize, currentTracerSize);
    CurrentTracerMGunImage.drawOval (0, 0, currentTracerSize, currentTracerSize);
    CurrentTracerMGunImage.setColor(currentColor);
    CurrentTracerMGunImage.fillOval (0, 0, currentTracerSize, currentTracerSize);
    setImage (CurrentTracerMGunImage);
    CurrentTracerMGunImage.setTransparency(currentTransparency);
}
...and it works, however, it slows down the simulation tremendously, and my laptop is not that old (Intel HD graphics, 8 GB DDR3 RAM, 1.9 Ghz...isn't that strange?
danpost danpost

2014/8/3

#
You do have multiple fields and local variables that are not necessary; and you do not have to create a new image each act cycle. Another problem may stem from the fact that you have the tracer objects extending the gun. The tracer is not, in itself, a gun, and therefore should not extend the gun. If you create a subclass of another class, you should be able to say that the object created from the subclass is a type of object that the superclass creates (just like an object from a subclass of World IS a world and an object from a subclass of Actor IS an actor).
getreides getreides

2014/8/4

#
Wow, there's still so much to learn for me, I really appreciate your help :-). So there are three things to do here: 1. get rid of all unnecessary (local) variables -> done, in all classes, as far as I could identify them 2. Only create subclasses of (sub-)classes if the means justify it according to what you wrote -> here: make the TracerGun class rather a subclass of ACTOR-superclass than of my class MGun (I will ASAP) 3. change the color of the existing TracerGun not by removing objects/recreating them with new color -> I would need help here. My current code of the changeColor() - method looks like this:
1
2
3
4
5
6
7
8
9
GreenComponent = GreenComponent + 5;
Color currentColor = new Color (255, GreenComponent, 0);
 
GreenfootImage CurrentTracerMGunImage = new GreenfootImage (this.TracerSize, this.TracerSize);         
CurrentTracerMGunImage.drawOval (0, 0, this.TracerSize, this.TracerSize);                              
CurrentTracerMGunImage.setColor(currentColor);
CurrentTracerMGunImage.fillOval (0, 0, this.TracerSize, this.TracerSize);                              
setImage (CurrentTracerMGunImage);
CurrentTracerMGunImage.setTransparency(this.transparency);
How can avoid creating a new image (and thereby) object if
1
2
GreenComponent = GreenComponent + 8
getImage().setColor(TracerColor); 
doesn't work?
danpost danpost

2014/8/4

#
The following method can be used in conjunction with one int field to track the act methods passed to control the image of the actor. The act method should increment the field and either update the image or remove the actor from the world depending on the value of the field. The field can also be used within the method to determine the new 'size', 'greenComponent' and 'transparency' values.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
private void updateImage()
{
    GreenfootImage image = getImage();
    image.clear();
    size = /* new size */;
    image.scale(size, size);
    image.setColor(Color.black);
    image.drawOval(0, 0, size, size);
    greenComponent = /* new greenComponent value */;
    image.setColor(new Color(255, greenComponent, 0));
    image.fillOval(0, 0, size, size);
    transparency = /* new transparency */
    image.setTransparency(transparency);
}
getreides getreides

2014/8/7

#
Thank you so much, I'll try that out an let you know :-)
getreides getreides

2014/8/13

#
Your code does work, thanks again! However, the performance has not improved - I think it's my laptop after all :-).
danpost danpost

2014/8/13

#
You might want to post the class code so it can be verified. Also, performance issues may, or may not, still be related to something in this class or some other code within your project.
getreides getreides

2014/8/15

#
Yes, I'll do that, I'll post the whole code in the scenario section and copy the link in this discussion - thanks again for your helpfulness, I really appreciate it!
getreides getreides

2014/8/15

#
Done, see on Shooter with tracers Looking forward to your feedback!
danpost danpost

2014/8/15

#
I did not notice any significant performance problems with the scenario; even with an abundance of tracers. The only (somewhat insignificant) problems I found as far as the code so far were: (1) you are setting the drawing color to the loaded MGun image to black, but not painting the image; also, sizing the image before painting the image would be wise (less area to paint -- hence less CPU time to perform the action). (2) you are loading the image for the MGun, then changing its size and painting the entire area of the image; there is no need to even load an image if you are to change it entirely; just change the default image, like so:
1
2
3
4
5
6
7
8
public MGun(int playerRotation)
{
    setRotation(playerRotation + Greenfoot.getRandomNumber(3) - 1);
    getImage().scale(4, 4);
    getImage().setColor(Color.black);
    getImage().fill();
    actCycle = 1.0;
}
It might not be so bad to create a new image here, as you are only creating an MGun once every 4 act cycles when the space is pressed. This will avoid dealing with the larger image at all and avoid multiple 'getImage' method calls:
1
2
3
4
5
6
7
8
public MGun(int playerRotation)
{
    setRotation(playerRotation + Greenfoot.getRandomNumber(3) -1);
    GreenfootImage image = new GreenfootImage(4, 4);
    image.fill(); // default drawing color for new GreenfootImage is black
    setImage(image);
    actCycle = 1.0;
}
(3) line 30 seems to be unnecessarily multiplying and dividing by the same value (1.01); maybe you meant to divide by (1.01 * 1.01) with the product inside parenthesis.
getreides getreides

2014/8/16

#
Wow, you never cease to amaze me :-). I will work on the code in the days to come; first of all, I will implement vector movement (that will make (3) superfluous - this was a somewhat awkward way to simulate gravity, and I kept trying various values until I got fed up with it and left line 30 the way it was at that moment).
You need to login to post a reply.