Have tried debugging by using System.out to check whether a method is run or not. The run method executes fine and the radar begins spinning with the robot console displaying Hello. onScannedRobot seems to be never called. Completely out of a clue of how to resolve. In the battle, the robot compiles fine into the game and it definitely is spinning its radar across other bots.
package ke_shen;
import robocode.util.*;
import robocode.*;
import java.util.*;
import java.awt.Color;
import java.awt.geom.Point2D;
//Oldest Scanned Radar
//Functions by spinning until all robots have been scanned
//then begins to scan in the opposite direction until
//all robots have been scanned again
//this minimizes the time in between all robots in the battlefield
//can be scanned, maximizing speed of scanning
public class shen_robot extends AdvancedRobot {
// the use of a linked hash map is deal here to store the enemy
// robot's names (the key)and their respective absolute bearings (thevalue)
static double scanDirection;
static Object sought;
static Object mostDanger = null;
static double distance = 50000;
static int tempindex = 0;
static int mostDangerIndex;
ArrayList<String> names = new ArrayList<String>();
ArrayList<Double> distanceArray = new ArrayList<Double>();
ArrayList<Double> velocityArray = new ArrayList<Double>();
ArrayList<Double> headingArray = new ArrayList<Double>();
public void run() {
setAdjustRadarForRobotTurn(true);
setAdjustGunForRobotTurn(true);
setAdjustRadarForGunTurn(true);
setAllColors(Color.BLUE);
System.out.println("Hello.");
scanDirection = 1;
// below, scanDirection will be become either negative or positive
// this changes the direction of the scan from initially
// clockwise to counterclockwise and vice versa;
setTurnRadarRightRadians(scanDirection * Double.POSITIVE_INFINITY);
scan();
// linearTargeting();
// execute();
}
// removes the robot from the hash map when it dies
public void onRobotDeathEvent(RobotDeathEvent e) {
int index = names.indexOf(e.getName());
names.remove(e.getName());
distanceArray.remove(index);
velocityArray.remove(index);
headingArray.remove(index);
}
public void onScannedRobot(ScannedRobotEvent e) {
System.out.println("Helo.");
// RADAR
// the radar will spin in a full circle once in the beginning of the
// battle
// and add all the robots to the hash map
// the second rotation, once it reaches the last robot in the hash map,
// because the radar heading is now greater than the normalRelative
// angle
// scanDirection will become negative, resulting in the radar spinning
// in the other
// direction due to the code above in line 31
// UPDATES PROPERTIES AFTER THE INITIAL 360 degree SCAN
String name = e.getName();
if (names.contains(name) == true) {
tempindex = names.indexOf(name);
headingArray.remove(tempindex);
headingArray.add(tempindex, e.getHeadingRadians());
velocityArray.remove(tempindex);
velocityArray.add(tempindex, e.getVelocity());
distanceArray.remove(tempindex);
distanceArray.add(tempindex, e.getDistance());
}
// HEADING
else {
int index = names.size()-1;
headingArray.add(e.getHeadingRadians());
if (names.size() == getOthers()) {
scanDirection = Utils.normalRelativeAngle(headingArray.get(index) - getRadarHeadingRadians());
}
// VELOCITY
velocityArray.add(e.getVelocity());
// DISTANCE & MOSTDANGEROUS
distanceArray.add(e.getDistance());
}
while (distanceArray.iterator().hasNext()) {
if (distanceArray.iterator().next() < distance) {
distance = distanceArray.iterator().next();
}
}
mostDangerIndex = distanceArray.indexOf(distance);
}
public void addInfo(String name, int number) {
}
}
Trivial Test
Changing OnScannedRobot to this allows it to execute normally. So the robot is catching the on scan events:
public void onScannedRobot(ScannedRobotEvent e) {
System.out.println("Helo.");
}
Diagnose the Problem
The issue is that if a robot fails to complete his turn in the time allotted, the turn will be skipped. Now the question is, what piece of the OnScannedRobot method is time inefficient?
Resolution
As it turns out, the mostDangerIndex calculation (that includes the while loop) is the culprit. So to fix the OnScannedRobot method, I replaced the mostDangerIndex calculation (that includes the while loop) with:
mostDangerIndex = distanceArray.indexOf(Collections.min(distanceArray));
Now it works!
Related
I am writing code for a school project that will be used for a Chromebook charging station with security. The problem I am having now is when I am detecting if a Chromebook is actually in the slot after the user has been assigned one, I am using a rocker switch to simulate this but when I am declaring the pin to the rocker, the arduino verfier comes up with that
"'slot1' does not name a type".
Code is below:
//class
class Chromebook_slot {
public:
String Name = "";
String RFID_tag = "";
int rocker = 0;
boolean chromebook_in = false;
//class function to check if chromebook is in.
//if not, redirect already to reassigning so chromebook slot is entered as open and free.
void set_if_in()
{
int momen_1_state = digitalRead(momen_1);
int momen_2_state = digitalRead(momen_2);
// the button has been pushed down and the previous process has been completed
// eg. servos would have been reset if there was a previous user
if (momen_1_state == HIGH || momen_2_state == HIGH)
{
chromebook_in = digitalRead(this->rocker);
if (chromebook_in == 0)
{
re_assigning();
}
else
{
return;
}
}
}
};
//this is now outside the class..
//class declarations
Chromebook_slot slot1;
Chromebook_slot slot2;
//variables for rocker switches which will act for detecting chromebooks.
// in my final version, this will replaced by a photoresistor and laser.
slot1.rocker = 3;
slot2.rocker = 2;
Where the function re_assigning() is a separate function declared further in the code and just resets the slot as open for future use.
slot1.rocker = 3;
slot2.rocker = 2;
These are statements that cannot be at the top level of a C++ (or .ino) file. They need to be inside of a function. What's happening is the compiler is looking looking at the slot1 identifier through the lens of potential valid constructions. It sees an identifier, and about the only thing that could legally exist at this point in the code that starts with an identifier like that is some declaration, e.g. int a = 7;, or more abstractly some_type some_more_stuff. So it expects slot1 to be a type, which it isn't, hence the message.
If you want an assignment like those to happen early on in an Arduino program, the simplest thing you could do is put them in setup():
void setup() {
slot1.rocker = 3;
slot2.rocker = 2;
// ...
}
Or, you'd make these part of the Chromebook_slot's constructor, such that they could be given in slot1 and slot2's declaration:
class Chromebook_slot {
public:
Chromebook_slot(int rocker_init_value) {
rocker = rocker_init_value;
}
// ...
Or in a maybe less familiar but more proper form, using the constructor's initialization list:
class Chromebook_slot {
public:
Chromebook_slot(int rocker_init_value)
: rocker(rocker_init_value) {}
// ...
Once you have a constructor for Chromebook_slot, your variables can become:
Chromebook_slot slot1(3);
Chromebook_slot slot2(2);
Generalities : explanations about my program and its functioning
I am working on a photo-retouching JavaFX application. The final user can load several images. When he clicks on the button REVERSE, a Task is launched for each image using an Executor. Each of these Task executes the reversal algorithm : it fills an ArrayBlockingQueue<Pixel> (using add method).
When the final user clicks on the button REVERSE, as I said, these Task are launched. But just after these statements, I tell the JavaFX Application Thread to draw the Pixel of the ArrayBlockingQueue<Pixel> (using remove method).
Thus, there are parallelism and concurrency (solved by the ArrayBlockingQueue<Pixel>) between the JavaFX Application Thread and the Task, and between the Task themselves.
To draw the Pixel of the ArrayBlockingQueue<Pixel>, the JavaFX Application Thread starts an AnimationTimer. The latter contains the previously-mentionned remove method. This AnimationTimer is started for each image.
I think you're wondering yourself how this AnimationTimer can know to what image belongs the Pixel it has removed ? In fact, each Pixel has an attribute writable_image that specifies the image to what it belongs.
My problems
Tell me if I'm wrong, but my program should work. Indeed :
My JavaFX Application Thread is the only thread that change the GUI (and it's required in JavaFX) : the Task just do the calculations.
There is not concurrency, thanks to the BlockingQueue I use (in particular, there isn't possibility of draining).
The AnimationTimer knows to what image belongs each Pixel.
However, it's (obviously !) not the case (otherwise I wouldn't have created this question haha !).
My problem is that my JavaFX Application freezes (first problem), after having drawn only some reversed pixels (not all the pixels). On the last loaded image moreover (third problem).
A detail that could be the problems' cause
But I would need your opinion.
The AnimationTimer of course doesn't draw the reversed pixels of each image directly : this is animated. The final user can see each pixel of an image being reversed, little by little. It's very practical in other algorithms as the creation of a circle, because the user can "look" how the algorithm works.
But to do that, the AnimationTimer needs to read a variable called max. This variable is modified (writen) in... each Task. But it's an AtomicLong. So IF I AM NOT WRONG, there isn't any problem of concurrency between the Task themselves, or between the JavaFX Application Thread and these Task.
However, it could be the problem : indeed, the max's value could be 2000 in Task n°1 (= in image n°1), and 59 in Task n°2 (= in image n°2). The problem is the AnimationTimer must use 2000 for the image n°1, and 59 for the n°2. But if the Task n°1 et n°2 have finished, the only value known by the AnimationTimer would be 59...
Sources
When the user clicks on the button REVERSE
We launch the several Task and start several times the AnimationTimer. CLASS : RightPane.java
WritableImage current_writable_image;
for(int i = 0; i < this.gui.getArrayListImageViewsImpacted().size(); i++) {
current_writable_image = (WritableImage) this.gui.getArrayListImageViewsImpacted().get(i).getImage();
this.gui.getGraphicEngine().executor.execute(this.gui.getGraphicEngine().createTask(current_writable_image));
}
for(int i = 0; i < this.gui.getArrayListImageViewsImpacted().size(); i++) {
current_writable_image = (WritableImage) this.gui.getArrayListImageViewsImpacted().get(i).getImage();
this.gui.getImageAnimation().setWritableImage(current_writable_image);
this.gui.getImageAnimation().startAnimation();
}
The Task are part of the CLASS GraphicEngine, which contains an Executor :
public final Executor executor = Executors.newCachedThreadPool(runnable -> {
Thread t = new Thread(runnable);
t.setDaemon(true);
return t ;
});
public Task createTask(WritableImage writable_image) {
int image_width = (int) writable_image.getWidth(), image_height = (int) writable_image.getHeight();
Task ret = new Task() {
protected Void call() {
switch(operation_to_do) {
case "reverse" :
gui.getImageAnimation().setMax(image_width*image_height); // USE OF "MAX" VARIABLE
reverseImg(writable_image);
break;
}
return null;
}
};
return ret;
}
The same CLASS, GraphicEngine, also contains the reversal algorithm :
private void reverseImg(WritableImage writable_image) {
int image_width = (int) writable_image.getWidth(), image_height = (int) writable_image.getHeight();
BlockingQueue<Pixel> updates = gui.getUpdates();
PixelReader pixel_reader = writable_image.getPixelReader();
double[] rgb_reversed;
for (int x = 0; x < image_width; x++) {
for (int y = 0; y < image_height; y++) {
rgb_reversed = PhotoRetouchingFormulas.reverse(pixel_reader.getColor(x, y).getRed(), pixel_reader.getColor(x, y).getGreen(), pixel_reader.getColor(x, y).getBlue());
updates.add(new Pixel(x, y, Color.color(rgb_reversed[0], rgb_reversed[1], rgb_reversed[2], pixel_reader.getColor(x, y).getOpacity()), writable_image));
}
}
}
Finally, here is the code of the CLASS AnimationTimer. There is nothing particular. Note the variable max is used here too (and in the CLASS GraphicEngine : setMax).
public class ImageAnimation extends AnimationTimer {
private Gui gui;
private AtomicLong max, speed, max_delay;
private long count, start;
private WritableImage writable_image;
ImageAnimation (Gui gui) {
this.gui = gui;
this.count = 0;
this.start = -1;
this.max = new AtomicLong(Long.MAX_VALUE);
this.max_delay = new AtomicLong(999_000_000);
this.speed = new AtomicLong(this.max_delay.get());
}
public void setMax(long max) {
this.max.set(max);
}
public void setSpeed(long speed) { this.speed.set(speed); }
public double getMaxDelay() { return this.max_delay.get(); }
#Override
public void handle(long timestamp) {
if (start < 0) {
start = timestamp ;
return ;
}
ArrayList<Pixel> list_sorted_pixels = new ArrayList<>();
BlockingQueue<Pixel> updates = this.gui.getUpdates();
for(Pixel new_pixel : updates) {
if(new_pixel.getWritableImage() == writable_image) {
list_sorted_pixels.add(new_pixel);
}
}
while (list_sorted_pixels.size() > 0 && timestamp - start > (count * this.speed.get()) / (writable_image.getWidth()) && !updates.isEmpty()) {
Pixel update = list_sorted_pixels.remove(0);
updates.remove(update);
count++;
if (update.getX() >= 0 && update.getY() >= 0) {
writable_image.getPixelWriter().setColor(update.getX(), update.getY(), update.getColor());
}
}
if (count >= max.get()) {
this.count = 0;
this.start = -1;
this.max.set(Long.MAX_VALUE);
stop();
}
}
public void setWritableImage(WritableImage writable_image) { this.writable_image = writable_image; }
public void startAnimation() {
this.start();
}
}
I have written a script that I have attached to Player which upon collecting a Magnet Power-Up, finds all the active GameObjects with a tag Treasure and makes them follow Player.
The thing is that I want all the active Treasure GameObjects not to only follow but actually go towards and collide with the Player so that points are collected.
Below is my code so far, any help is appreciated.
using UnityEngine;
using System.Collections;
public class TreasureFollowPlayer : MonoBehaviour {
public GameObject[] treasures;
public bool magnetPowerUpEnabled = false;
void OnTriggerEnter2D(Collider2D col)
{
if (col.CompareTag("Magnetpowerup"))
{
col.gameObject.SetActive(false);
magnetPowerUpEnabled = true;
}
}
// Update is called once per frame
void Update() {
if (magnetPowerUpEnabled)
{
treasures = GameObject.FindGameObjectsWithTag("Treasure");
foreach (var treasure in treasures)
{
treasure.transform.position = Vector2.MoveTowards(treasure.transform.position, transform.position, 1.0f * Time.deltaTime);
}
}
}
}
You will need to ensure the treasure moves faster than the player so it can catch up for starters. Then have a small script either on the treasure or the player which checks for onTriggerEnter calls. When the treasure touches the player then fire off a function destroying or disabling it and increase the players score however is appropriate.
In my app, I have a searchbox which allows users to filter as they type. For some reason I can't get an InfinteProgress to properly display while the filtering is being executed.
Here's my code:
Pass 1
public void renderForumList(){
try{
magnify = mStateMachine.findForumSearchIcon(form);
}catch(NullPointerException ex){
System.out.println("User typed additional character in search term before previous term finished executing");
}
InfiniteProgress infi = new InfiniteProgress();
magnify.getParent().replace(magnify, infi, null);
Display.getInstance().invokeAndBlock(new Runnable() {
#Override
public void run() {
for (int i = 0;i < containerStates.length;i++){
if(containerStates[i] != listItems[i].isVisible()){
listItems[i].setHidden(!containerStates[i]);
listItems[i].setVisible(containerStates[i]);
}
}
Display.getInstance().callSerially(new Runnable() {
#Override
public void run() {
mStateMachine.findForumsListComponent(form).animateLayout(200);
mStateMachine.findContainer2(form).replace(infi, magnify, null);
}
});
}
});
}
In this version, the infinite progress shows up in the proper position, but it doesn't spin.
Pass 2
public void renderForumList(){
try{
magnify = mStateMachine.findForumSearchIcon(form);
}catch(NullPointerException ex){
System.out.println("User typed additional character in search term before previous term finished executing");
}
InfiniteProgress infi = new InfiniteProgress();
magnify.getParent().replace(magnify, infi, null);
for (int i = 0;i < containerStates.length;i++){
if(containerStates[i] != listItems[i].isVisible()){
listItems[i].setHidden(!containerStates[i]);
listItems[i].setVisible(containerStates[i]);
}
}
mStateMachine.findForumsListComponent(form).animateLayout(200);
mStateMachine.findContainer2(form).replace(infi, magnify, null);
}
}
}
In this version, the magnifier icon just flashes briefly, but the InfiniteProgress spinner is never visible.
I get the same results on the simulator and on an Android device.
How can I get the InfiniteProgress to spin while the search is taking place?
invokeAndBlock opens a new thread and thus violates the EDT as you access UI components on a separate thread.
Try using callSerially instead to postpone the following code into the next EDT cycle although I'm not sure that will help as everything is still happening on the EDT.
Alternatively I'm guessing the method isVisible takes time, so you can enclose that call alone in invokeAndBlock.
To understand invokeAndBlock check out the developer guide https://www.codenameone.com/manual/edt.html
I am making a super simple watchface for the pebble using SDK 2. The watchface compiles and install but the clock does not update. I have attached my code below. Any ideas?
#include <pebble.h>
static Window *s_main_window;
static TextLayer *s_time_layer;
static TextLayer *s_date_layer;
static GFont s_time_font;
static BitmapLayer *s_background_layer;
static GBitmap *s_background_bitmap;
static void update_time() {
// Get a tm structure
time_t temp = time(NULL);
struct tm *tick_time = localtime(&temp);
// Create a long-lived buffer
static char buffer[] = ">00:00";
// Write the current hours and minutes into the buffer
if(clock_is_24h_style() == true) {
//Use 2h hour format
strftime(buffer, sizeof(">00:00"), ">%H:%M", tick_time);
} else {
//Use 12 hour format
strftime(buffer, sizeof(">00:00"), ">%I:%M", tick_time);
}
// Display this time on the TextLayer
text_layer_set_text(s_time_layer, buffer);
}
static void update_date(){
time_t temp = time(NULL);
struct tm *tick_time = localtime(&temp);
static char buffer[] = ">00/00/00";
strftime(buffer, sizeof(">00/00/00"), ">%D", tick_time);
text_layer_set_text(s_date_layer, buffer);
}
static void main_window_load(Window *window) {
//Create Gbitmap, then set to created bitmap layer
s_background_bitmap = gbitmap_create_with_resource(RESOURCE_ID_lenny);
s_background_layer = bitmap_layer_create(GRect(0, 0, 144, 168));
bitmap_layer_set_bitmap(s_background_layer, s_background_bitmap);
layer_add_child(window_get_root_layer(window), bitmap_layer_get_layer(s_background_layer));
// Create time TextLayer
s_time_layer = text_layer_create(GRect(5, 90, 144, 50));
text_layer_set_background_color(s_time_layer, GColorClear);
text_layer_set_text_color(s_time_layer, GColorBlack);
text_layer_set_text(s_time_layer, ">00:00");
//Create date TextLayer
s_date_layer = text_layer_create(GRect(5, 115, 144, 50));
text_layer_set_background_color(s_date_layer, GColorClear);
text_layer_set_text_color(s_date_layer, GColorBlack);
text_layer_set_text(s_date_layer, ">00/00/00");
//Create GFont
s_time_font = fonts_load_custom_font(resource_get_handle(RESOURCE_ID_arial25));
//Apply to TextLayer
text_layer_set_font(s_time_layer, s_time_font);
text_layer_set_text_alignment(s_time_layer, GTextAlignmentLeft);
text_layer_set_font(s_date_layer, s_time_font);
text_layer_set_text_alignment(s_date_layer, GTextAlignmentLeft);
// Add it as a child layer to the Window's root layer
layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_time_layer));
layer_add_child(window_get_root_layer(window), text_layer_get_layer(s_date_layer));
// Make sure the time is displayed from the start
update_time();
update_date();
}
static void main_window_unload(Window *window) {
//Unload GFont
fonts_unload_custom_font(s_time_font);
// Destroy TextLayer
text_layer_destroy(s_time_layer);
//Destroy Gbitmap
gbitmap_destroy(s_background_bitmap);
//Destroy BitmapLayer
bitmap_layer_destroy(s_background_layer);
//Destroy datelayer
text_layer_destroy(s_date_layer);
}
static void tick_handler(struct tm *tick_time, TimeUnits units_changed) {
update_time();
}
static void tick_handler_date(struct tm *tick_time, TimeUnits units_changed){
update_date();
}
static void init() {
// Create main Window element and assign to pointer
s_main_window = window_create();
// Set handlers to manage the elements inside the Window
window_set_window_handlers(s_main_window, (WindowHandlers) {
.load = main_window_load,
.unload = main_window_unload
});
// Show the Window on the watch, with animated=true
window_stack_push(s_main_window, true);
// Register with TickTimerService
tick_timer_service_subscribe(MINUTE_UNIT, tick_handler);
tick_timer_service_subscribe(DAY_UNIT, tick_handler_date);
}
static void deinit() {
// Destroy Window
window_destroy(s_main_window);
}
int main(void) {
init();
app_event_loop();
deinit();
}
There is a true type font being used as well as a png. These can be replaced with anything for testing purposes as long as the reference ID's in the code are changed as well. Any help is greatly appreciated. Thanks !
It's because you override checking every minute and updating the time here:
tick_timer_service_subscribe(DAY_UNIT, tick_handler_date);
tick_timer_service_subscribe takes a unit and a function pointer. When you called it the second time you overrode the unit and the function pointer.
Instead you should call it once with MINUTE_UNIT and tick_handler. Then inside tick_handler write a new function called update_date_and_time. This function does what it says, updates the date and the time. You'll unnecessarily update the date most of the time, but that's okay, because you'll correctly update the time.